12439e4bfSJean-Christophe PLAGNIOL-VILLARD /************************************************************************** 2ac3315c2SAndre Schwarz Intel Pro 1000 for ppcboot/das-u-boot 32439e4bfSJean-Christophe PLAGNIOL-VILLARD Drivers are port from Intel's Linux driver e1000-4.3.15 42439e4bfSJean-Christophe PLAGNIOL-VILLARD and from Etherboot pro 1000 driver by mrakes at vivato dot net 52439e4bfSJean-Christophe PLAGNIOL-VILLARD tested on both gig copper and gig fiber boards 62439e4bfSJean-Christophe PLAGNIOL-VILLARD ***************************************************************************/ 72439e4bfSJean-Christophe PLAGNIOL-VILLARD /******************************************************************************* 82439e4bfSJean-Christophe PLAGNIOL-VILLARD 92439e4bfSJean-Christophe PLAGNIOL-VILLARD 102439e4bfSJean-Christophe PLAGNIOL-VILLARD Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. 112439e4bfSJean-Christophe PLAGNIOL-VILLARD 122439e4bfSJean-Christophe PLAGNIOL-VILLARD This program is free software; you can redistribute it and/or modify it 132439e4bfSJean-Christophe PLAGNIOL-VILLARD under the terms of the GNU General Public License as published by the Free 142439e4bfSJean-Christophe PLAGNIOL-VILLARD Software Foundation; either version 2 of the License, or (at your option) 152439e4bfSJean-Christophe PLAGNIOL-VILLARD any later version. 162439e4bfSJean-Christophe PLAGNIOL-VILLARD 172439e4bfSJean-Christophe PLAGNIOL-VILLARD This program is distributed in the hope that it will be useful, but WITHOUT 182439e4bfSJean-Christophe PLAGNIOL-VILLARD ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 192439e4bfSJean-Christophe PLAGNIOL-VILLARD FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 202439e4bfSJean-Christophe PLAGNIOL-VILLARD more details. 212439e4bfSJean-Christophe PLAGNIOL-VILLARD 222439e4bfSJean-Christophe PLAGNIOL-VILLARD You should have received a copy of the GNU General Public License along with 232439e4bfSJean-Christophe PLAGNIOL-VILLARD this program; if not, write to the Free Software Foundation, Inc., 59 242439e4bfSJean-Christophe PLAGNIOL-VILLARD Temple Place - Suite 330, Boston, MA 02111-1307, USA. 252439e4bfSJean-Christophe PLAGNIOL-VILLARD 262439e4bfSJean-Christophe PLAGNIOL-VILLARD The full GNU General Public License is included in this distribution in the 272439e4bfSJean-Christophe PLAGNIOL-VILLARD file called LICENSE. 282439e4bfSJean-Christophe PLAGNIOL-VILLARD 292439e4bfSJean-Christophe PLAGNIOL-VILLARD Contact Information: 302439e4bfSJean-Christophe PLAGNIOL-VILLARD Linux NICS <linux.nics@intel.com> 312439e4bfSJean-Christophe PLAGNIOL-VILLARD Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 322439e4bfSJean-Christophe PLAGNIOL-VILLARD 332439e4bfSJean-Christophe PLAGNIOL-VILLARD *******************************************************************************/ 342439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 352439e4bfSJean-Christophe PLAGNIOL-VILLARD * Copyright (C) Archway Digital Solutions. 362439e4bfSJean-Christophe PLAGNIOL-VILLARD * 372439e4bfSJean-Christophe PLAGNIOL-VILLARD * written by Chrsitopher Li <cli at arcyway dot com> or <chrisl at gnuchina dot org> 382439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2/9/2002 392439e4bfSJean-Christophe PLAGNIOL-VILLARD * 402439e4bfSJean-Christophe PLAGNIOL-VILLARD * Copyright (C) Linux Networx. 412439e4bfSJean-Christophe PLAGNIOL-VILLARD * Massive upgrade to work with the new intel gigabit NICs. 422439e4bfSJean-Christophe PLAGNIOL-VILLARD * <ebiederman at lnxi dot com> 432439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 442439e4bfSJean-Christophe PLAGNIOL-VILLARD 452439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "e1000.h" 462439e4bfSJean-Christophe PLAGNIOL-VILLARD 472439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_CMD_NET) \ 482439e4bfSJean-Christophe PLAGNIOL-VILLARD && defined(CONFIG_NET_MULTI) && defined(CONFIG_E1000) 492439e4bfSJean-Christophe PLAGNIOL-VILLARD 502439e4bfSJean-Christophe PLAGNIOL-VILLARD #define TOUT_LOOP 100000 512439e4bfSJean-Christophe PLAGNIOL-VILLARD 522439e4bfSJean-Christophe PLAGNIOL-VILLARD #undef virt_to_bus 532439e4bfSJean-Christophe PLAGNIOL-VILLARD #define virt_to_bus(x) ((unsigned long)x) 542439e4bfSJean-Christophe PLAGNIOL-VILLARD #define bus_to_phys(devno, a) pci_mem_to_phys(devno, a) 552439e4bfSJean-Christophe PLAGNIOL-VILLARD #define mdelay(n) udelay((n)*1000) 562439e4bfSJean-Christophe PLAGNIOL-VILLARD 572439e4bfSJean-Christophe PLAGNIOL-VILLARD #define E1000_DEFAULT_PBA 0x00000030 582439e4bfSJean-Christophe PLAGNIOL-VILLARD 592439e4bfSJean-Christophe PLAGNIOL-VILLARD /* NIC specific static variables go here */ 602439e4bfSJean-Christophe PLAGNIOL-VILLARD 612439e4bfSJean-Christophe PLAGNIOL-VILLARD static char tx_pool[128 + 16]; 622439e4bfSJean-Christophe PLAGNIOL-VILLARD static char rx_pool[128 + 16]; 632439e4bfSJean-Christophe PLAGNIOL-VILLARD static char packet[2096]; 642439e4bfSJean-Christophe PLAGNIOL-VILLARD 652439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct e1000_tx_desc *tx_base; 662439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct e1000_rx_desc *rx_base; 672439e4bfSJean-Christophe PLAGNIOL-VILLARD 682439e4bfSJean-Christophe PLAGNIOL-VILLARD static int tx_tail; 692439e4bfSJean-Christophe PLAGNIOL-VILLARD static int rx_tail, rx_last; 702439e4bfSJean-Christophe PLAGNIOL-VILLARD 712439e4bfSJean-Christophe PLAGNIOL-VILLARD static struct pci_device_id supported[] = { 722439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82542}, 732439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_FIBER}, 742439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_COPPER}, 752439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_COPPER}, 762439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544EI_FIBER}, 772439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_COPPER}, 782439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82544GC_LOM}, 792439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM}, 802439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_COPPER}, 812439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_COPPER}, 822439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_FIBER}, 832439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_FIBER}, 842439e4bfSJean-Christophe PLAGNIOL-VILLARD {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM_LOM}, 85ac3315c2SAndre Schwarz {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541ER}, 86*aa3b8bf9SWolfgang Grandegger {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541GI_LF}, 872439e4bfSJean-Christophe PLAGNIOL-VILLARD }; 882439e4bfSJean-Christophe PLAGNIOL-VILLARD 892439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Function forward declarations */ 902439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_setup_link(struct eth_device *nic); 912439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_setup_fiber_link(struct eth_device *nic); 922439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_setup_copper_link(struct eth_device *nic); 932439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_phy_setup_autoneg(struct e1000_hw *hw); 942439e4bfSJean-Christophe PLAGNIOL-VILLARD static void e1000_config_collision_dist(struct e1000_hw *hw); 952439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_config_mac_to_phy(struct e1000_hw *hw); 962439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_config_fc_after_link_up(struct e1000_hw *hw); 972439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_check_for_link(struct eth_device *nic); 982439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_wait_autoneg(struct e1000_hw *hw); 992439e4bfSJean-Christophe PLAGNIOL-VILLARD static void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, 1002439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t * duplex); 1012439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, 1022439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t * phy_data); 1032439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, 1042439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t phy_data); 1052439e4bfSJean-Christophe PLAGNIOL-VILLARD static void e1000_phy_hw_reset(struct e1000_hw *hw); 1062439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_phy_reset(struct e1000_hw *hw); 1072439e4bfSJean-Christophe PLAGNIOL-VILLARD static int e1000_detect_gig_phy(struct e1000_hw *hw); 1082439e4bfSJean-Christophe PLAGNIOL-VILLARD 1092439e4bfSJean-Christophe PLAGNIOL-VILLARD #define E1000_WRITE_REG(a, reg, value) (writel((value), ((a)->hw_addr + E1000_##reg))) 1102439e4bfSJean-Christophe PLAGNIOL-VILLARD #define E1000_READ_REG(a, reg) (readl((a)->hw_addr + E1000_##reg)) 1112439e4bfSJean-Christophe PLAGNIOL-VILLARD #define E1000_WRITE_REG_ARRAY(a, reg, offset, value) (\ 1122439e4bfSJean-Christophe PLAGNIOL-VILLARD writel((value), ((a)->hw_addr + E1000_##reg + ((offset) << 2)))) 1132439e4bfSJean-Christophe PLAGNIOL-VILLARD #define E1000_READ_REG_ARRAY(a, reg, offset) ( \ 1142439e4bfSJean-Christophe PLAGNIOL-VILLARD readl((a)->hw_addr + E1000_##reg + ((offset) << 2))) 1152439e4bfSJean-Christophe PLAGNIOL-VILLARD #define E1000_WRITE_FLUSH(a) {uint32_t x; x = E1000_READ_REG(a, STATUS);} 1162439e4bfSJean-Christophe PLAGNIOL-VILLARD 1172439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_AP1000 /* remove for warnings */ 1182439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 1192439e4bfSJean-Christophe PLAGNIOL-VILLARD * Raises the EEPROM's clock input. 1202439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1212439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 1222439e4bfSJean-Christophe PLAGNIOL-VILLARD * eecd - EECD's current value 1232439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 1242439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 1252439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t * eecd) 1262439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1272439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Raise the clock input to the EEPROM (by setting the SK bit), and then 1282439e4bfSJean-Christophe PLAGNIOL-VILLARD * wait 50 microseconds. 1292439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1302439e4bfSJean-Christophe PLAGNIOL-VILLARD *eecd = *eecd | E1000_EECD_SK; 1312439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, *eecd); 1322439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 1332439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(50); 1342439e4bfSJean-Christophe PLAGNIOL-VILLARD } 1352439e4bfSJean-Christophe PLAGNIOL-VILLARD 1362439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 1372439e4bfSJean-Christophe PLAGNIOL-VILLARD * Lowers the EEPROM's clock input. 1382439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1392439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 1402439e4bfSJean-Christophe PLAGNIOL-VILLARD * eecd - EECD's current value 1412439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 1422439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 1432439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t * eecd) 1442439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1452439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Lower the clock input to the EEPROM (by clearing the SK bit), and then 1462439e4bfSJean-Christophe PLAGNIOL-VILLARD * wait 50 microseconds. 1472439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1482439e4bfSJean-Christophe PLAGNIOL-VILLARD *eecd = *eecd & ~E1000_EECD_SK; 1492439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, *eecd); 1502439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 1512439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(50); 1522439e4bfSJean-Christophe PLAGNIOL-VILLARD } 1532439e4bfSJean-Christophe PLAGNIOL-VILLARD 1542439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 1552439e4bfSJean-Christophe PLAGNIOL-VILLARD * Shift data bits out to the EEPROM. 1562439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1572439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 1582439e4bfSJean-Christophe PLAGNIOL-VILLARD * data - data to send to the EEPROM 1592439e4bfSJean-Christophe PLAGNIOL-VILLARD * count - number of bits to shift out 1602439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 1612439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 1622439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count) 1632439e4bfSJean-Christophe PLAGNIOL-VILLARD { 1642439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t eecd; 1652439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t mask; 1662439e4bfSJean-Christophe PLAGNIOL-VILLARD 1672439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We need to shift "count" bits out to the EEPROM. So, value in the 1682439e4bfSJean-Christophe PLAGNIOL-VILLARD * "data" parameter will be shifted out to the EEPROM one bit at a time. 1692439e4bfSJean-Christophe PLAGNIOL-VILLARD * In order to do this, "data" must be broken down into bits. 1702439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1712439e4bfSJean-Christophe PLAGNIOL-VILLARD mask = 0x01 << (count - 1); 1722439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 1732439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); 1742439e4bfSJean-Christophe PLAGNIOL-VILLARD do { 1752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1", 1762439e4bfSJean-Christophe PLAGNIOL-VILLARD * and then raising and then lowering the clock (the SK bit controls 1772439e4bfSJean-Christophe PLAGNIOL-VILLARD * the clock input to the EEPROM). A "0" is shifted out to the EEPROM 1782439e4bfSJean-Christophe PLAGNIOL-VILLARD * by setting "DI" to "0" and then raising and then lowering the clock. 1792439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 1802439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~E1000_EECD_DI; 1812439e4bfSJean-Christophe PLAGNIOL-VILLARD 1822439e4bfSJean-Christophe PLAGNIOL-VILLARD if (data & mask) 1832439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd |= E1000_EECD_DI; 1842439e4bfSJean-Christophe PLAGNIOL-VILLARD 1852439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 1862439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 1872439e4bfSJean-Christophe PLAGNIOL-VILLARD 1882439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(50); 1892439e4bfSJean-Christophe PLAGNIOL-VILLARD 1902439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_ee_clk(hw, &eecd); 1912439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_ee_clk(hw, &eecd); 1922439e4bfSJean-Christophe PLAGNIOL-VILLARD 1932439e4bfSJean-Christophe PLAGNIOL-VILLARD mask = mask >> 1; 1942439e4bfSJean-Christophe PLAGNIOL-VILLARD 1952439e4bfSJean-Christophe PLAGNIOL-VILLARD } while (mask); 1962439e4bfSJean-Christophe PLAGNIOL-VILLARD 1972439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We leave the "DI" bit set to "0" when we leave this routine. */ 1982439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~E1000_EECD_DI; 1992439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 2002439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2012439e4bfSJean-Christophe PLAGNIOL-VILLARD 2022439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 2032439e4bfSJean-Christophe PLAGNIOL-VILLARD * Shift data bits in from the EEPROM 2042439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2052439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 2062439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 2072439e4bfSJean-Christophe PLAGNIOL-VILLARD static uint16_t 2082439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_in_ee_bits(struct e1000_hw *hw) 2092439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2102439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t eecd; 2112439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t i; 2122439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t data; 2132439e4bfSJean-Christophe PLAGNIOL-VILLARD 2142439e4bfSJean-Christophe PLAGNIOL-VILLARD /* In order to read a register from the EEPROM, we need to shift 16 bits 2152439e4bfSJean-Christophe PLAGNIOL-VILLARD * in from the EEPROM. Bits are "shifted in" by raising the clock input to 2162439e4bfSJean-Christophe PLAGNIOL-VILLARD * the EEPROM (setting the SK bit), and then reading the value of the "DO" 2172439e4bfSJean-Christophe PLAGNIOL-VILLARD * bit. During this "shifting in" process the "DI" bit should always be 2182439e4bfSJean-Christophe PLAGNIOL-VILLARD * clear.. 2192439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 2202439e4bfSJean-Christophe PLAGNIOL-VILLARD 2212439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 2222439e4bfSJean-Christophe PLAGNIOL-VILLARD 2232439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); 2242439e4bfSJean-Christophe PLAGNIOL-VILLARD data = 0; 2252439e4bfSJean-Christophe PLAGNIOL-VILLARD 2262439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 16; i++) { 2272439e4bfSJean-Christophe PLAGNIOL-VILLARD data = data << 1; 2282439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_ee_clk(hw, &eecd); 2292439e4bfSJean-Christophe PLAGNIOL-VILLARD 2302439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 2312439e4bfSJean-Christophe PLAGNIOL-VILLARD 2322439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~(E1000_EECD_DI); 2332439e4bfSJean-Christophe PLAGNIOL-VILLARD if (eecd & E1000_EECD_DO) 2342439e4bfSJean-Christophe PLAGNIOL-VILLARD data |= 1; 2352439e4bfSJean-Christophe PLAGNIOL-VILLARD 2362439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_ee_clk(hw, &eecd); 2372439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2382439e4bfSJean-Christophe PLAGNIOL-VILLARD 2392439e4bfSJean-Christophe PLAGNIOL-VILLARD return data; 2402439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2412439e4bfSJean-Christophe PLAGNIOL-VILLARD 2422439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 2432439e4bfSJean-Christophe PLAGNIOL-VILLARD * Prepares EEPROM for access 2442439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2452439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 2462439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2472439e4bfSJean-Christophe PLAGNIOL-VILLARD * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This 2482439e4bfSJean-Christophe PLAGNIOL-VILLARD * function should be called before issuing a command to the EEPROM. 2492439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 2502439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 2512439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_eeprom(struct e1000_hw *hw) 2522439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2532439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t eecd; 2542439e4bfSJean-Christophe PLAGNIOL-VILLARD 2552439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 2562439e4bfSJean-Christophe PLAGNIOL-VILLARD 2572439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear SK and DI */ 2582439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~(E1000_EECD_SK | E1000_EECD_DI); 2592439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 2602439e4bfSJean-Christophe PLAGNIOL-VILLARD 2612439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set CS */ 2622439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd |= E1000_EECD_CS; 2632439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 2642439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2652439e4bfSJean-Christophe PLAGNIOL-VILLARD 2662439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 2672439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns EEPROM to a "standby" state 2682439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2692439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 2702439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 2712439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 2722439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_standby_eeprom(struct e1000_hw *hw) 2732439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2742439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t eecd; 2752439e4bfSJean-Christophe PLAGNIOL-VILLARD 2762439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 2772439e4bfSJean-Christophe PLAGNIOL-VILLARD 2782439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Deselct EEPROM */ 2792439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); 2802439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 2812439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 2822439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(50); 2832439e4bfSJean-Christophe PLAGNIOL-VILLARD 2842439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clock high */ 2852439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd |= E1000_EECD_SK; 2862439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 2872439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 2882439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(50); 2892439e4bfSJean-Christophe PLAGNIOL-VILLARD 2902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Select EEPROM */ 2912439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd |= E1000_EECD_CS; 2922439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 2932439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 2942439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(50); 2952439e4bfSJean-Christophe PLAGNIOL-VILLARD 2962439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clock low */ 2972439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~E1000_EECD_SK; 2982439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 2992439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 3002439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(50); 3012439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3022439e4bfSJean-Christophe PLAGNIOL-VILLARD 3032439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 3042439e4bfSJean-Christophe PLAGNIOL-VILLARD * Reads a 16 bit word from the EEPROM. 3052439e4bfSJean-Christophe PLAGNIOL-VILLARD * 3062439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 3072439e4bfSJean-Christophe PLAGNIOL-VILLARD * offset - offset of word in the EEPROM to read 3082439e4bfSJean-Christophe PLAGNIOL-VILLARD * data - word read from the EEPROM 3092439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 3102439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 3112439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, uint16_t * data) 3122439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3132439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t eecd; 3142439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t i = 0; 3152439e4bfSJean-Christophe PLAGNIOL-VILLARD int large_eeprom = FALSE; 3162439e4bfSJean-Christophe PLAGNIOL-VILLARD 3172439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Request EEPROM Access */ 3182439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82544) { 3192439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 3202439e4bfSJean-Christophe PLAGNIOL-VILLARD if (eecd & E1000_EECD_SIZE) 3212439e4bfSJean-Christophe PLAGNIOL-VILLARD large_eeprom = TRUE; 3222439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd |= E1000_EECD_REQ; 3232439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 3242439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 3252439e4bfSJean-Christophe PLAGNIOL-VILLARD while ((!(eecd & E1000_EECD_GNT)) && (i < 100)) { 3262439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 3272439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10); 3282439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 3292439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3302439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(eecd & E1000_EECD_GNT)) { 3312439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~E1000_EECD_REQ; 3322439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 3332439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Could not acquire EEPROM grant\n"); 3342439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_EEPROM; 3352439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3362439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3372439e4bfSJean-Christophe PLAGNIOL-VILLARD 3382439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Prepare the EEPROM for reading */ 3392439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_eeprom(hw); 3402439e4bfSJean-Christophe PLAGNIOL-VILLARD 3412439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Send the READ command (opcode + addr) */ 3422439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE, 3); 3432439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, offset, (large_eeprom) ? 8 : 6); 3442439e4bfSJean-Christophe PLAGNIOL-VILLARD 3452439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the data */ 3462439e4bfSJean-Christophe PLAGNIOL-VILLARD *data = e1000_shift_in_ee_bits(hw); 3472439e4bfSJean-Christophe PLAGNIOL-VILLARD 3482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* End this read operation */ 3492439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_standby_eeprom(hw); 3502439e4bfSJean-Christophe PLAGNIOL-VILLARD 3512439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Stop requesting EEPROM access */ 3522439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82544) { 3532439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 3542439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~E1000_EECD_REQ; 3552439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 3562439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3572439e4bfSJean-Christophe PLAGNIOL-VILLARD 3582439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 3592439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3602439e4bfSJean-Christophe PLAGNIOL-VILLARD 3612439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 3622439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 3632439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_eeprom_cleanup(struct e1000_hw *hw) 3642439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3652439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t eecd; 3662439e4bfSJean-Christophe PLAGNIOL-VILLARD 3672439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 3682439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); 3692439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 3702439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_ee_clk(hw, &eecd); 3712439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_ee_clk(hw, &eecd); 3722439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3732439e4bfSJean-Christophe PLAGNIOL-VILLARD 3742439e4bfSJean-Christophe PLAGNIOL-VILLARD static uint16_t 3752439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_wait_eeprom_done(struct e1000_hw *hw) 3762439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3772439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t eecd; 3782439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t i; 3792439e4bfSJean-Christophe PLAGNIOL-VILLARD 3802439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_standby_eeprom(hw); 3812439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 200; i++) { 3822439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 3832439e4bfSJean-Christophe PLAGNIOL-VILLARD if (eecd & E1000_EECD_DO) 3842439e4bfSJean-Christophe PLAGNIOL-VILLARD return (TRUE); 3852439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(5); 3862439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3872439e4bfSJean-Christophe PLAGNIOL-VILLARD return (FALSE); 3882439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3892439e4bfSJean-Christophe PLAGNIOL-VILLARD 3902439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 3912439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_write_eeprom(struct e1000_hw *hw, uint16_t Reg, uint16_t Data) 3922439e4bfSJean-Christophe PLAGNIOL-VILLARD { 3932439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t eecd; 3942439e4bfSJean-Christophe PLAGNIOL-VILLARD int large_eeprom = FALSE; 3952439e4bfSJean-Christophe PLAGNIOL-VILLARD int i = 0; 3962439e4bfSJean-Christophe PLAGNIOL-VILLARD 3972439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Request EEPROM Access */ 3982439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82544) { 3992439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 4002439e4bfSJean-Christophe PLAGNIOL-VILLARD if (eecd & E1000_EECD_SIZE) 4012439e4bfSJean-Christophe PLAGNIOL-VILLARD large_eeprom = TRUE; 4022439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd |= E1000_EECD_REQ; 4032439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 4042439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 4052439e4bfSJean-Christophe PLAGNIOL-VILLARD while ((!(eecd & E1000_EECD_GNT)) && (i < 100)) { 4062439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 4072439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(5); 4082439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 4092439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4102439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(eecd & E1000_EECD_GNT)) { 4112439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~E1000_EECD_REQ; 4122439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 4132439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Could not acquire EEPROM grant\n"); 4142439e4bfSJean-Christophe PLAGNIOL-VILLARD return FALSE; 4152439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4162439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4172439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_eeprom(hw); 4182439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE, 5); 4192439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 6 : 4); 4202439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_standby_eeprom(hw); 4212439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE, 3); 4222439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 8 : 6); 4232439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, Data, 16); 4242439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!e1000_wait_eeprom_done(hw)) { 4252439e4bfSJean-Christophe PLAGNIOL-VILLARD return FALSE; 4262439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4272439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE, 5); 4282439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_ee_bits(hw, Reg, (large_eeprom) ? 6 : 4); 4292439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_eeprom_cleanup(hw); 4302439e4bfSJean-Christophe PLAGNIOL-VILLARD 4312439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Stop requesting EEPROM access */ 4322439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82544) { 4332439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 4342439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd &= ~E1000_EECD_REQ; 4352439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, EECD, eecd); 4362439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4372439e4bfSJean-Christophe PLAGNIOL-VILLARD i = 0; 4382439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 4392439e4bfSJean-Christophe PLAGNIOL-VILLARD while (((eecd & E1000_EECD_GNT)) && (i < 500)) { 4402439e4bfSJean-Christophe PLAGNIOL-VILLARD i++; 4412439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10); 4422439e4bfSJean-Christophe PLAGNIOL-VILLARD eecd = E1000_READ_REG(hw, EECD); 4432439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4442439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((eecd & E1000_EECD_GNT)) { 4452439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Could not release EEPROM grant\n"); 4462439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4472439e4bfSJean-Christophe PLAGNIOL-VILLARD return TRUE; 4482439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4492439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 4502439e4bfSJean-Christophe PLAGNIOL-VILLARD 4512439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 4522439e4bfSJean-Christophe PLAGNIOL-VILLARD * Verifies that the EEPROM has a valid checksum 4532439e4bfSJean-Christophe PLAGNIOL-VILLARD * 4542439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 4552439e4bfSJean-Christophe PLAGNIOL-VILLARD * 4562439e4bfSJean-Christophe PLAGNIOL-VILLARD * Reads the first 64 16 bit words of the EEPROM and sums the values read. 4572439e4bfSJean-Christophe PLAGNIOL-VILLARD * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is 4582439e4bfSJean-Christophe PLAGNIOL-VILLARD * valid. 4592439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 4602439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 4612439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_validate_eeprom_checksum(struct eth_device *nic) 4622439e4bfSJean-Christophe PLAGNIOL-VILLARD { 4632439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 4642439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t checksum = 0; 4652439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t i, eeprom_data; 4662439e4bfSJean-Christophe PLAGNIOL-VILLARD 4672439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 4682439e4bfSJean-Christophe PLAGNIOL-VILLARD 4692439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { 4702439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_eeprom(hw, i, &eeprom_data) < 0) { 4712439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("EEPROM Read Error\n"); 4722439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_EEPROM; 4732439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4742439e4bfSJean-Christophe PLAGNIOL-VILLARD checksum += eeprom_data; 4752439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4762439e4bfSJean-Christophe PLAGNIOL-VILLARD 4772439e4bfSJean-Christophe PLAGNIOL-VILLARD if (checksum == (uint16_t) EEPROM_SUM) { 4782439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 4792439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 4802439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("EEPROM Checksum Invalid\n"); 4812439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_EEPROM; 4822439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4832439e4bfSJean-Christophe PLAGNIOL-VILLARD } 4842439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* #ifndef CONFIG_AP1000 */ 4852439e4bfSJean-Christophe PLAGNIOL-VILLARD 4862439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 4872439e4bfSJean-Christophe PLAGNIOL-VILLARD * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the 4882439e4bfSJean-Christophe PLAGNIOL-VILLARD * second function of dual function devices 4892439e4bfSJean-Christophe PLAGNIOL-VILLARD * 4902439e4bfSJean-Christophe PLAGNIOL-VILLARD * nic - Struct containing variables accessed by shared code 4912439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 4922439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 4932439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_read_mac_addr(struct eth_device *nic) 4942439e4bfSJean-Christophe PLAGNIOL-VILLARD { 4952439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_AP1000 4962439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 4972439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t offset; 4982439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t eeprom_data; 4992439e4bfSJean-Christophe PLAGNIOL-VILLARD int i; 5002439e4bfSJean-Christophe PLAGNIOL-VILLARD 5012439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 5022439e4bfSJean-Christophe PLAGNIOL-VILLARD 5032439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { 5042439e4bfSJean-Christophe PLAGNIOL-VILLARD offset = i >> 1; 5052439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_eeprom(hw, offset, &eeprom_data) < 0) { 5062439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("EEPROM Read Error\n"); 5072439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_EEPROM; 5082439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5092439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->enetaddr[i] = eeprom_data & 0xff; 5102439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->enetaddr[i + 1] = (eeprom_data >> 8) & 0xff; 5112439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5122439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((hw->mac_type == e1000_82546) && 5132439e4bfSJean-Christophe PLAGNIOL-VILLARD (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { 5142439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Invert the last bit if this is the second device */ 5152439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->enetaddr[5] += 1; 5162439e4bfSJean-Christophe PLAGNIOL-VILLARD } 517ac3315c2SAndre Schwarz #ifdef CONFIG_E1000_FALLBACK_MAC 518ac3315c2SAndre Schwarz if ( *(u32*)(nic->enetaddr) == 0 || *(u32*)(nic->enetaddr) == ~0 ) 519ac3315c2SAndre Schwarz for ( i=0; i < NODE_ADDRESS_SIZE; i++ ) 520ac3315c2SAndre Schwarz nic->enetaddr[i] = (CONFIG_E1000_FALLBACK_MAC >> (8*(5-i))) & 0xff; 521ac3315c2SAndre Schwarz #endif 5222439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 5232439e4bfSJean-Christophe PLAGNIOL-VILLARD /* 5242439e4bfSJean-Christophe PLAGNIOL-VILLARD * The AP1000's e1000 has no eeprom; the MAC address is stored in the 5252439e4bfSJean-Christophe PLAGNIOL-VILLARD * environment variables. Currently this does not support the addition 5262439e4bfSJean-Christophe PLAGNIOL-VILLARD * of a PMC e1000 card, which is certainly a possibility, so this should 5272439e4bfSJean-Christophe PLAGNIOL-VILLARD * be updated to properly use the env variable only for the onboard e1000 5282439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 5292439e4bfSJean-Christophe PLAGNIOL-VILLARD 5302439e4bfSJean-Christophe PLAGNIOL-VILLARD int ii; 5312439e4bfSJean-Christophe PLAGNIOL-VILLARD char *s, *e; 5322439e4bfSJean-Christophe PLAGNIOL-VILLARD 5332439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 5342439e4bfSJean-Christophe PLAGNIOL-VILLARD 5352439e4bfSJean-Christophe PLAGNIOL-VILLARD s = getenv ("ethaddr"); 5362439e4bfSJean-Christophe PLAGNIOL-VILLARD if (s == NULL){ 5372439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_EEPROM; 5382439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5392439e4bfSJean-Christophe PLAGNIOL-VILLARD else{ 5402439e4bfSJean-Christophe PLAGNIOL-VILLARD for(ii = 0; ii < 6; ii++) { 5412439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->enetaddr[ii] = s ? simple_strtoul (s, &e, 16) : 0; 5422439e4bfSJean-Christophe PLAGNIOL-VILLARD if (s){ 5432439e4bfSJean-Christophe PLAGNIOL-VILLARD s = (*e) ? e + 1 : e; 5442439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5452439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5462439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5472439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 5482439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 5492439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5502439e4bfSJean-Christophe PLAGNIOL-VILLARD 5512439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 5522439e4bfSJean-Christophe PLAGNIOL-VILLARD * Initializes receive address filters. 5532439e4bfSJean-Christophe PLAGNIOL-VILLARD * 5542439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 5552439e4bfSJean-Christophe PLAGNIOL-VILLARD * 5562439e4bfSJean-Christophe PLAGNIOL-VILLARD * Places the MAC address in receive address register 0 and clears the rest 5572439e4bfSJean-Christophe PLAGNIOL-VILLARD * of the receive addresss registers. Clears the multicast table. Assumes 5582439e4bfSJean-Christophe PLAGNIOL-VILLARD * the receiver is in reset when the routine is called. 5592439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 5602439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 5612439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_init_rx_addrs(struct eth_device *nic) 5622439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5632439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 5642439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t i; 5652439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t addr_low; 5662439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t addr_high; 5672439e4bfSJean-Christophe PLAGNIOL-VILLARD 5682439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 5692439e4bfSJean-Christophe PLAGNIOL-VILLARD 5702439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Setup the receive address. */ 5712439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Programming MAC Address into RAR[0]\n"); 5722439e4bfSJean-Christophe PLAGNIOL-VILLARD addr_low = (nic->enetaddr[0] | 5732439e4bfSJean-Christophe PLAGNIOL-VILLARD (nic->enetaddr[1] << 8) | 5742439e4bfSJean-Christophe PLAGNIOL-VILLARD (nic->enetaddr[2] << 16) | (nic->enetaddr[3] << 24)); 5752439e4bfSJean-Christophe PLAGNIOL-VILLARD 5762439e4bfSJean-Christophe PLAGNIOL-VILLARD addr_high = (nic->enetaddr[4] | (nic->enetaddr[5] << 8) | E1000_RAH_AV); 5772439e4bfSJean-Christophe PLAGNIOL-VILLARD 5782439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low); 5792439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high); 5802439e4bfSJean-Christophe PLAGNIOL-VILLARD 5812439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Zero out the other 15 receive addresses. */ 5822439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Clearing RAR[1-15]\n"); 5832439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 1; i < E1000_RAR_ENTRIES; i++) { 5842439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); 5852439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); 5862439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5872439e4bfSJean-Christophe PLAGNIOL-VILLARD } 5882439e4bfSJean-Christophe PLAGNIOL-VILLARD 5892439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 5902439e4bfSJean-Christophe PLAGNIOL-VILLARD * Clears the VLAN filer table 5912439e4bfSJean-Christophe PLAGNIOL-VILLARD * 5922439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 5932439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 5942439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 5952439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_clear_vfta(struct e1000_hw *hw) 5962439e4bfSJean-Christophe PLAGNIOL-VILLARD { 5972439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t offset; 5982439e4bfSJean-Christophe PLAGNIOL-VILLARD 5992439e4bfSJean-Christophe PLAGNIOL-VILLARD for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) 6002439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0); 6012439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6022439e4bfSJean-Christophe PLAGNIOL-VILLARD 6032439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 6042439e4bfSJean-Christophe PLAGNIOL-VILLARD * Set the mac type member in the hw struct. 6052439e4bfSJean-Christophe PLAGNIOL-VILLARD * 6062439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 6072439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 6082439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 6092439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_set_mac_type(struct e1000_hw *hw) 6102439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6112439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 6122439e4bfSJean-Christophe PLAGNIOL-VILLARD 6132439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (hw->device_id) { 6142439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82542: 6152439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (hw->revision_id) { 6162439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_82542_2_0_REV_ID: 6172439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mac_type = e1000_82542_rev2_0; 6182439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 6192439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_82542_2_1_REV_ID: 6202439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mac_type = e1000_82542_rev2_1; 6212439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 6222439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 6232439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Invalid 82542 revision ID */ 6242439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_MAC_TYPE; 6252439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6262439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 6272439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82543GC_FIBER: 6282439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82543GC_COPPER: 6292439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mac_type = e1000_82543; 6302439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 6312439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82544EI_COPPER: 6322439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82544EI_FIBER: 6332439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82544GC_COPPER: 6342439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82544GC_LOM: 6352439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mac_type = e1000_82544; 6362439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 6372439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82540EM: 6382439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82540EM_LOM: 6392439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mac_type = e1000_82540; 6402439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 6412439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82545EM_COPPER: 6422439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82545EM_FIBER: 6432439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mac_type = e1000_82545; 6442439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 6452439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82546EB_COPPER: 6462439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_DEV_ID_82546EB_FIBER: 6472439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mac_type = e1000_82546; 6482439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 649ac3315c2SAndre Schwarz case E1000_DEV_ID_82541ER: 650*aa3b8bf9SWolfgang Grandegger case E1000_DEV_ID_82541GI_LF: 651ac3315c2SAndre Schwarz hw->mac_type = e1000_82541_rev_2; 652ac3315c2SAndre Schwarz break; 6532439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 6542439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Should never have loaded on this device */ 6552439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_MAC_TYPE; 6562439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6572439e4bfSJean-Christophe PLAGNIOL-VILLARD return E1000_SUCCESS; 6582439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6592439e4bfSJean-Christophe PLAGNIOL-VILLARD 6602439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 6612439e4bfSJean-Christophe PLAGNIOL-VILLARD * Reset the transmit and receive units; mask and clear all interrupts. 6622439e4bfSJean-Christophe PLAGNIOL-VILLARD * 6632439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 6642439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 6652439e4bfSJean-Christophe PLAGNIOL-VILLARD void 6662439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_reset_hw(struct e1000_hw *hw) 6672439e4bfSJean-Christophe PLAGNIOL-VILLARD { 6682439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 6692439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl_ext; 6702439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t icr; 6712439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t manc; 6722439e4bfSJean-Christophe PLAGNIOL-VILLARD 6732439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 6742439e4bfSJean-Christophe PLAGNIOL-VILLARD 6752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ 6762439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type == e1000_82542_rev2_0) { 6772439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); 6782439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_word(hw->pdev, PCI_COMMAND, 6792439e4bfSJean-Christophe PLAGNIOL-VILLARD hw-> 6802439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_cmd_word & ~PCI_COMMAND_INVALIDATE); 6812439e4bfSJean-Christophe PLAGNIOL-VILLARD } 6822439e4bfSJean-Christophe PLAGNIOL-VILLARD 6832439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear interrupt mask to stop board from generating interrupts */ 6842439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Masking off all interrupts\n"); 6852439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, IMC, 0xffffffff); 6862439e4bfSJean-Christophe PLAGNIOL-VILLARD 6872439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disable the Transmit and Receive units. Then delay to allow 6882439e4bfSJean-Christophe PLAGNIOL-VILLARD * any pending transactions to complete before we hit the MAC with 6892439e4bfSJean-Christophe PLAGNIOL-VILLARD * the global reset. 6902439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 6912439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, 0); 6922439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP); 6932439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 6942439e4bfSJean-Christophe PLAGNIOL-VILLARD 6952439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ 6962439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->tbi_compatibility_on = FALSE; 6972439e4bfSJean-Christophe PLAGNIOL-VILLARD 6982439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Delay to allow any outstanding PCI transactions to complete before 6992439e4bfSJean-Christophe PLAGNIOL-VILLARD * resetting the device 7002439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7012439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(10); 7022439e4bfSJean-Christophe PLAGNIOL-VILLARD 7032439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Issue a global reset to the MAC. This will reset the chip's 7042439e4bfSJean-Christophe PLAGNIOL-VILLARD * transmit, receive, DMA, and link units. It will not effect 7052439e4bfSJean-Christophe PLAGNIOL-VILLARD * the current PCI configuration. The global reset bit is self- 7062439e4bfSJean-Christophe PLAGNIOL-VILLARD * clearing, and should clear within a microsecond. 7072439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 7082439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Issuing a global reset to MAC\n"); 7092439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 7102439e4bfSJean-Christophe PLAGNIOL-VILLARD 7112439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 7122439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82543) 7132439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); 7142439e4bfSJean-Christophe PLAGNIOL-VILLARD else 7152439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 7162439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); 7172439e4bfSJean-Christophe PLAGNIOL-VILLARD 7182439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Force a reload from the EEPROM if necessary */ 7192439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type < e1000_82540) { 7202439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for reset to complete */ 7212439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10); 7222439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); 7232439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl_ext |= E1000_CTRL_EXT_EE_RST; 7242439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); 7252439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 7262439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for EEPROM reload */ 7272439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(2); 7282439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 7292439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Wait for EEPROM reload (it happens automatically) */ 7302439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(4); 7312439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Dissable HW ARPs on ASF enabled adapters */ 7322439e4bfSJean-Christophe PLAGNIOL-VILLARD manc = E1000_READ_REG(hw, MANC); 7332439e4bfSJean-Christophe PLAGNIOL-VILLARD manc &= ~(E1000_MANC_ARP_EN); 7342439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, MANC, manc); 7352439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7362439e4bfSJean-Christophe PLAGNIOL-VILLARD 7372439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear interrupt mask to stop board from generating interrupts */ 7382439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Masking off all interrupts\n"); 7392439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, IMC, 0xffffffff); 7402439e4bfSJean-Christophe PLAGNIOL-VILLARD 7412439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear any pending interrupt events. */ 7422439e4bfSJean-Christophe PLAGNIOL-VILLARD icr = E1000_READ_REG(hw, ICR); 7432439e4bfSJean-Christophe PLAGNIOL-VILLARD 7442439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If MWI was previously enabled, reenable it. */ 7452439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type == e1000_82542_rev2_0) { 7462439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); 7472439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7482439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7492439e4bfSJean-Christophe PLAGNIOL-VILLARD 7502439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 7512439e4bfSJean-Christophe PLAGNIOL-VILLARD * Performs basic configuration of the adapter. 7522439e4bfSJean-Christophe PLAGNIOL-VILLARD * 7532439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 7542439e4bfSJean-Christophe PLAGNIOL-VILLARD * 7552439e4bfSJean-Christophe PLAGNIOL-VILLARD * Assumes that the controller has previously been reset and is in a 7562439e4bfSJean-Christophe PLAGNIOL-VILLARD * post-reset uninitialized state. Initializes the receive address registers, 7572439e4bfSJean-Christophe PLAGNIOL-VILLARD * multicast table, and VLAN filter table. Calls routines to setup link 7582439e4bfSJean-Christophe PLAGNIOL-VILLARD * configuration and flow control settings. Clears all on-chip counters. Leaves 7592439e4bfSJean-Christophe PLAGNIOL-VILLARD * the transmit and receive units disabled and uninitialized. 7602439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 7612439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 7622439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_init_hw(struct eth_device *nic) 7632439e4bfSJean-Christophe PLAGNIOL-VILLARD { 7642439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 7652439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl, status; 7662439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t i; 7672439e4bfSJean-Christophe PLAGNIOL-VILLARD int32_t ret_val; 7682439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t pcix_cmd_word; 7692439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t pcix_stat_hi_word; 7702439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t cmd_mmrbc; 7712439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t stat_mmrbc; 7722439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_bus_type bus_type = e1000_bus_type_unknown; 7732439e4bfSJean-Christophe PLAGNIOL-VILLARD 7742439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 7752439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 7762439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Initialize Identification LED */ 7772439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_id_led_init(hw); 7782439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 7792439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error Initializing Identification LED\n"); 7802439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 7812439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7822439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 7832439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the Media Type and exit with error if it is not valid. */ 7842439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type != e1000_82543) { 7852439e4bfSJean-Christophe PLAGNIOL-VILLARD /* tbi_compatibility is only valid on 82543 */ 7862439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->tbi_compatibility_en = FALSE; 7872439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7882439e4bfSJean-Christophe PLAGNIOL-VILLARD 7892439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82543) { 7902439e4bfSJean-Christophe PLAGNIOL-VILLARD status = E1000_READ_REG(hw, STATUS); 7912439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & E1000_STATUS_TBIMODE) { 7922439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->media_type = e1000_media_type_fiber; 7932439e4bfSJean-Christophe PLAGNIOL-VILLARD /* tbi_compatibility not valid on fiber */ 7942439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->tbi_compatibility_en = FALSE; 7952439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 7962439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->media_type = e1000_media_type_copper; 7972439e4bfSJean-Christophe PLAGNIOL-VILLARD } 7982439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 7992439e4bfSJean-Christophe PLAGNIOL-VILLARD /* This is an 82542 (fiber only) */ 8002439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->media_type = e1000_media_type_fiber; 8012439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8022439e4bfSJean-Christophe PLAGNIOL-VILLARD 8032439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disabling VLAN filtering. */ 8042439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Initializing the IEEE VLAN\n"); 8052439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, VET, 0); 8062439e4bfSJean-Christophe PLAGNIOL-VILLARD 8072439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_clear_vfta(hw); 8082439e4bfSJean-Christophe PLAGNIOL-VILLARD 8092439e4bfSJean-Christophe PLAGNIOL-VILLARD /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ 8102439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type == e1000_82542_rev2_0) { 8112439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); 8122439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_word(hw->pdev, PCI_COMMAND, 8132439e4bfSJean-Christophe PLAGNIOL-VILLARD hw-> 8142439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_cmd_word & ~PCI_COMMAND_INVALIDATE); 8152439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST); 8162439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 8172439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(5); 8182439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8192439e4bfSJean-Christophe PLAGNIOL-VILLARD 8202439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Setup the receive address. This involves initializing all of the Receive 8212439e4bfSJean-Christophe PLAGNIOL-VILLARD * Address Registers (RARs 0 - 15). 8222439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 8232439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_init_rx_addrs(nic); 8242439e4bfSJean-Christophe PLAGNIOL-VILLARD 8252439e4bfSJean-Christophe PLAGNIOL-VILLARD /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ 8262439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type == e1000_82542_rev2_0) { 8272439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, 0); 8282439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 8292439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(1); 8302439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); 8312439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8322439e4bfSJean-Christophe PLAGNIOL-VILLARD 8332439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Zero out the Multicast HASH table */ 8342439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Zeroing the MTA\n"); 8352439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < E1000_MC_TBL_SIZE; i++) 8362439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); 8372439e4bfSJean-Christophe PLAGNIOL-VILLARD 8382439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 8392439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the PCI priority bit correctly in the CTRL register. This 8402439e4bfSJean-Christophe PLAGNIOL-VILLARD * determines if the adapter gives priority to receives, or if it 8412439e4bfSJean-Christophe PLAGNIOL-VILLARD * gives equal priority to transmits and receives. 8422439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 8432439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->dma_fairness) { 8442439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 8452439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); 8462439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8472439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 8482439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82543) { 8492439e4bfSJean-Christophe PLAGNIOL-VILLARD status = E1000_READ_REG(hw, STATUS); 8502439e4bfSJean-Christophe PLAGNIOL-VILLARD bus_type = (status & E1000_STATUS_PCIX_MODE) ? 8512439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_bus_type_pcix : e1000_bus_type_pci; 8522439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8532439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ 8542439e4bfSJean-Christophe PLAGNIOL-VILLARD if (bus_type == e1000_bus_type_pcix) { 8552439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER, 8562439e4bfSJean-Christophe PLAGNIOL-VILLARD &pcix_cmd_word); 8572439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_word(hw->pdev, PCIX_STATUS_REGISTER_HI, 8582439e4bfSJean-Christophe PLAGNIOL-VILLARD &pcix_stat_hi_word); 8592439e4bfSJean-Christophe PLAGNIOL-VILLARD cmd_mmrbc = 8602439e4bfSJean-Christophe PLAGNIOL-VILLARD (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> 8612439e4bfSJean-Christophe PLAGNIOL-VILLARD PCIX_COMMAND_MMRBC_SHIFT; 8622439e4bfSJean-Christophe PLAGNIOL-VILLARD stat_mmrbc = 8632439e4bfSJean-Christophe PLAGNIOL-VILLARD (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> 8642439e4bfSJean-Christophe PLAGNIOL-VILLARD PCIX_STATUS_HI_MMRBC_SHIFT; 8652439e4bfSJean-Christophe PLAGNIOL-VILLARD if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) 8662439e4bfSJean-Christophe PLAGNIOL-VILLARD stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; 8672439e4bfSJean-Christophe PLAGNIOL-VILLARD if (cmd_mmrbc > stat_mmrbc) { 8682439e4bfSJean-Christophe PLAGNIOL-VILLARD pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; 8692439e4bfSJean-Christophe PLAGNIOL-VILLARD pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; 8702439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER, 8712439e4bfSJean-Christophe PLAGNIOL-VILLARD pcix_cmd_word); 8722439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8732439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8742439e4bfSJean-Christophe PLAGNIOL-VILLARD 8752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Call a subroutine to configure the link and setup flow control. */ 8762439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_setup_link(nic); 8772439e4bfSJean-Christophe PLAGNIOL-VILLARD 8782439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the transmit descriptor write-back policy */ 8792439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82544) { 8802439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, TXDCTL); 8812439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = 8822439e4bfSJean-Christophe PLAGNIOL-VILLARD (ctrl & ~E1000_TXDCTL_WTHRESH) | 8832439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_TXDCTL_FULL_TX_DESC_WB; 8842439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TXDCTL, ctrl); 8852439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8862439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 8872439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear all of the statistics registers (clear on read). It is 8882439e4bfSJean-Christophe PLAGNIOL-VILLARD * important that we do this after we have tried to establish link 8892439e4bfSJean-Christophe PLAGNIOL-VILLARD * because the symbol error count will increment wildly if there 8902439e4bfSJean-Christophe PLAGNIOL-VILLARD * is no link. 8912439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 8922439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_clear_hw_cntrs(hw); 8932439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 8942439e4bfSJean-Christophe PLAGNIOL-VILLARD 8952439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 8962439e4bfSJean-Christophe PLAGNIOL-VILLARD } 8972439e4bfSJean-Christophe PLAGNIOL-VILLARD 8982439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 8992439e4bfSJean-Christophe PLAGNIOL-VILLARD * Configures flow control and link settings. 9002439e4bfSJean-Christophe PLAGNIOL-VILLARD * 9012439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 9022439e4bfSJean-Christophe PLAGNIOL-VILLARD * 9032439e4bfSJean-Christophe PLAGNIOL-VILLARD * Determines which flow control settings to use. Calls the apropriate media- 9042439e4bfSJean-Christophe PLAGNIOL-VILLARD * specific link configuration function. Configures the flow control settings. 9052439e4bfSJean-Christophe PLAGNIOL-VILLARD * Assuming the adapter has a valid link partner, a valid link should be 9062439e4bfSJean-Christophe PLAGNIOL-VILLARD * established. Assumes the hardware has previously been reset and the 9072439e4bfSJean-Christophe PLAGNIOL-VILLARD * transmitter and receiver are not enabled. 9082439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 9092439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 9102439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_link(struct eth_device *nic) 9112439e4bfSJean-Christophe PLAGNIOL-VILLARD { 9122439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 9132439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl_ext; 9142439e4bfSJean-Christophe PLAGNIOL-VILLARD int32_t ret_val; 9152439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t eeprom_data; 9162439e4bfSJean-Christophe PLAGNIOL-VILLARD 9172439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 9182439e4bfSJean-Christophe PLAGNIOL-VILLARD 9192439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_AP1000 9202439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read and store word 0x0F of the EEPROM. This word contains bits 9212439e4bfSJean-Christophe PLAGNIOL-VILLARD * that determine the hardware's default PAUSE (flow control) mode, 9222439e4bfSJean-Christophe PLAGNIOL-VILLARD * a bit that determines whether the HW defaults to enabling or 9232439e4bfSJean-Christophe PLAGNIOL-VILLARD * disabling auto-negotiation, and the direction of the 9242439e4bfSJean-Christophe PLAGNIOL-VILLARD * SW defined pins. If there is no SW over-ride of the flow 9252439e4bfSJean-Christophe PLAGNIOL-VILLARD * control setting, then the variable hw->fc will 9262439e4bfSJean-Christophe PLAGNIOL-VILLARD * be initialized based on a value in the EEPROM. 9272439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 9282439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data) < 0) { 9292439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("EEPROM Read Error\n"); 9302439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_EEPROM; 9312439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9322439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 9332439e4bfSJean-Christophe PLAGNIOL-VILLARD /* we have to hardcode the proper value for our hardware. */ 9342439e4bfSJean-Christophe PLAGNIOL-VILLARD /* this value is for the 82540EM pci card used for prototyping, and it works. */ 9352439e4bfSJean-Christophe PLAGNIOL-VILLARD eeprom_data = 0xb220; 9362439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 9372439e4bfSJean-Christophe PLAGNIOL-VILLARD 9382439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->fc == e1000_fc_default) { 9392439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) 9402439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_none; 9412439e4bfSJean-Christophe PLAGNIOL-VILLARD else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 9422439e4bfSJean-Christophe PLAGNIOL-VILLARD EEPROM_WORD0F_ASM_DIR) 9432439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_tx_pause; 9442439e4bfSJean-Christophe PLAGNIOL-VILLARD else 9452439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_full; 9462439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9472439e4bfSJean-Christophe PLAGNIOL-VILLARD 9482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We want to save off the original Flow Control configuration just 9492439e4bfSJean-Christophe PLAGNIOL-VILLARD * in case we get disconnected and then reconnected into a different 9502439e4bfSJean-Christophe PLAGNIOL-VILLARD * hub or switch with different Flow Control capabilities. 9512439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 9522439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type == e1000_82542_rev2_0) 9532439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc &= (~e1000_fc_tx_pause); 9542439e4bfSJean-Christophe PLAGNIOL-VILLARD 9552439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1)) 9562439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc &= (~e1000_fc_rx_pause); 9572439e4bfSJean-Christophe PLAGNIOL-VILLARD 9582439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->original_fc = hw->fc; 9592439e4bfSJean-Christophe PLAGNIOL-VILLARD 9602439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("After fix-ups FlowControl is now = %x\n", hw->fc); 9612439e4bfSJean-Christophe PLAGNIOL-VILLARD 9622439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Take the 4 bits from EEPROM word 0x0F that determine the initial 9632439e4bfSJean-Christophe PLAGNIOL-VILLARD * polarity value for the SW controlled pins, and setup the 9642439e4bfSJean-Christophe PLAGNIOL-VILLARD * Extended Device Control reg with that info. 9652439e4bfSJean-Christophe PLAGNIOL-VILLARD * This is needed because one of the SW controlled pins is used for 9662439e4bfSJean-Christophe PLAGNIOL-VILLARD * signal detection. So this should be done before e1000_setup_pcs_link() 9672439e4bfSJean-Christophe PLAGNIOL-VILLARD * or e1000_phy_setup() is called. 9682439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 9692439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type == e1000_82543) { 9702439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << 9712439e4bfSJean-Christophe PLAGNIOL-VILLARD SWDPIO__EXT_SHIFT); 9722439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); 9732439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9742439e4bfSJean-Christophe PLAGNIOL-VILLARD 9752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Call the necessary subroutine to configure the link. */ 9762439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = (hw->media_type == e1000_media_type_fiber) ? 9772439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_fiber_link(nic) : e1000_setup_copper_link(nic); 9782439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 9792439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 9802439e4bfSJean-Christophe PLAGNIOL-VILLARD } 9812439e4bfSJean-Christophe PLAGNIOL-VILLARD 9822439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Initialize the flow control address, type, and PAUSE timer 9832439e4bfSJean-Christophe PLAGNIOL-VILLARD * registers to their default values. This is done even if flow 9842439e4bfSJean-Christophe PLAGNIOL-VILLARD * control is disabled, because it does not hurt anything to 9852439e4bfSJean-Christophe PLAGNIOL-VILLARD * initialize these registers. 9862439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 9872439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 9882439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Initializing the Flow Control address, type and timer regs\n"); 9892439e4bfSJean-Christophe PLAGNIOL-VILLARD 9902439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); 9912439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); 9922439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE); 9932439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time); 9942439e4bfSJean-Christophe PLAGNIOL-VILLARD 9952439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the flow control receive threshold registers. Normally, 9962439e4bfSJean-Christophe PLAGNIOL-VILLARD * these registers will be set to a default threshold that may be 9972439e4bfSJean-Christophe PLAGNIOL-VILLARD * adjusted later by the driver's runtime code. However, if the 9982439e4bfSJean-Christophe PLAGNIOL-VILLARD * ability to transmit pause frames in not enabled, then these 9992439e4bfSJean-Christophe PLAGNIOL-VILLARD * registers will be set to 0. 10002439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 10012439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(hw->fc & e1000_fc_tx_pause)) { 10022439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCRTL, 0); 10032439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCRTH, 0); 10042439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 10052439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We need to set up the Receive Threshold high and low water marks 10062439e4bfSJean-Christophe PLAGNIOL-VILLARD * as well as (optionally) enabling the transmission of XON frames. 10072439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 10082439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->fc_send_xon) { 10092439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCRTL, 10102439e4bfSJean-Christophe PLAGNIOL-VILLARD (hw->fc_low_water | E1000_FCRTL_XONE)); 10112439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); 10122439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 10132439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water); 10142439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water); 10152439e4bfSJean-Christophe PLAGNIOL-VILLARD } 10162439e4bfSJean-Christophe PLAGNIOL-VILLARD } 10172439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 10182439e4bfSJean-Christophe PLAGNIOL-VILLARD } 10192439e4bfSJean-Christophe PLAGNIOL-VILLARD 10202439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 10212439e4bfSJean-Christophe PLAGNIOL-VILLARD * Sets up link for a fiber based adapter 10222439e4bfSJean-Christophe PLAGNIOL-VILLARD * 10232439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 10242439e4bfSJean-Christophe PLAGNIOL-VILLARD * 10252439e4bfSJean-Christophe PLAGNIOL-VILLARD * Manipulates Physical Coding Sublayer functions in order to configure 10262439e4bfSJean-Christophe PLAGNIOL-VILLARD * link. Assumes the hardware has been previously reset and the transmitter 10272439e4bfSJean-Christophe PLAGNIOL-VILLARD * and receiver are not enabled. 10282439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 10292439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 10302439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_fiber_link(struct eth_device *nic) 10312439e4bfSJean-Christophe PLAGNIOL-VILLARD { 10322439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 10332439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 10342439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t status; 10352439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t txcw = 0; 10362439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t i; 10372439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t signal; 10382439e4bfSJean-Christophe PLAGNIOL-VILLARD int32_t ret_val; 10392439e4bfSJean-Christophe PLAGNIOL-VILLARD 10402439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 10412439e4bfSJean-Christophe PLAGNIOL-VILLARD /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be 10422439e4bfSJean-Christophe PLAGNIOL-VILLARD * set when the optics detect a signal. On older adapters, it will be 10432439e4bfSJean-Christophe PLAGNIOL-VILLARD * cleared when there is a signal 10442439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 10452439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 10462439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((hw->mac_type > e1000_82544) && !(ctrl & E1000_CTRL_ILOS)) 10472439e4bfSJean-Christophe PLAGNIOL-VILLARD signal = E1000_CTRL_SWDPIN1; 10482439e4bfSJean-Christophe PLAGNIOL-VILLARD else 10492439e4bfSJean-Christophe PLAGNIOL-VILLARD signal = 0; 10502439e4bfSJean-Christophe PLAGNIOL-VILLARD 10512439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("signal for %s is %x (ctrl %08x)!!!!\n", nic->name, signal, 10522439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl); 10532439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Take the link out of reset */ 10542439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= ~(E1000_CTRL_LRST); 10552439e4bfSJean-Christophe PLAGNIOL-VILLARD 10562439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_config_collision_dist(hw); 10572439e4bfSJean-Christophe PLAGNIOL-VILLARD 10582439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check for a software override of the flow control settings, and setup 10592439e4bfSJean-Christophe PLAGNIOL-VILLARD * the device accordingly. If auto-negotiation is enabled, then software 10602439e4bfSJean-Christophe PLAGNIOL-VILLARD * will have to set the "PAUSE" bits to the correct value in the Tranmsit 10612439e4bfSJean-Christophe PLAGNIOL-VILLARD * Config Word Register (TXCW) and re-start auto-negotiation. However, if 10622439e4bfSJean-Christophe PLAGNIOL-VILLARD * auto-negotiation is disabled, then software will have to manually 10632439e4bfSJean-Christophe PLAGNIOL-VILLARD * configure the two flow control enable bits in the CTRL register. 10642439e4bfSJean-Christophe PLAGNIOL-VILLARD * 10652439e4bfSJean-Christophe PLAGNIOL-VILLARD * The possible values of the "fc" parameter are: 10662439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0: Flow control is completely disabled 10672439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1: Rx flow control is enabled (we can receive pause frames, but 10682439e4bfSJean-Christophe PLAGNIOL-VILLARD * not send pause frames). 10692439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2: Tx flow control is enabled (we can send pause frames but we do 10702439e4bfSJean-Christophe PLAGNIOL-VILLARD * not support receiving pause frames). 10712439e4bfSJean-Christophe PLAGNIOL-VILLARD * 3: Both Rx and TX flow control (symmetric) are enabled. 10722439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 10732439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (hw->fc) { 10742439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_none: 10752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Flow control is completely disabled by a software over-ride. */ 10762439e4bfSJean-Christophe PLAGNIOL-VILLARD txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); 10772439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 10782439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_rx_pause: 10792439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RX Flow control is enabled and TX Flow control is disabled by a 10802439e4bfSJean-Christophe PLAGNIOL-VILLARD * software over-ride. Since there really isn't a way to advertise 10812439e4bfSJean-Christophe PLAGNIOL-VILLARD * that we are capable of RX Pause ONLY, we will advertise that we 10822439e4bfSJean-Christophe PLAGNIOL-VILLARD * support both symmetric and asymmetric RX PAUSE. Later, we will 10832439e4bfSJean-Christophe PLAGNIOL-VILLARD * disable the adapter's ability to send PAUSE frames. 10842439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 10852439e4bfSJean-Christophe PLAGNIOL-VILLARD txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); 10862439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 10872439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_tx_pause: 10882439e4bfSJean-Christophe PLAGNIOL-VILLARD /* TX Flow control is enabled, and RX Flow control is disabled, by a 10892439e4bfSJean-Christophe PLAGNIOL-VILLARD * software over-ride. 10902439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 10912439e4bfSJean-Christophe PLAGNIOL-VILLARD txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); 10922439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 10932439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_full: 10942439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Flow control (both RX and TX) is enabled by a software over-ride. */ 10952439e4bfSJean-Christophe PLAGNIOL-VILLARD txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); 10962439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 10972439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 10982439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Flow control param set incorrectly\n"); 10992439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_CONFIG; 11002439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 11012439e4bfSJean-Christophe PLAGNIOL-VILLARD } 11022439e4bfSJean-Christophe PLAGNIOL-VILLARD 11032439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Since auto-negotiation is enabled, take the link out of reset (the link 11042439e4bfSJean-Christophe PLAGNIOL-VILLARD * will be in reset, because we previously reset the chip). This will 11052439e4bfSJean-Christophe PLAGNIOL-VILLARD * restart auto-negotiation. If auto-neogtiation is successful then the 11062439e4bfSJean-Christophe PLAGNIOL-VILLARD * link-up status bit will be set and the flow control enable bits (RFCE 11072439e4bfSJean-Christophe PLAGNIOL-VILLARD * and TFCE) will be set according to their negotiated value. 11082439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 11092439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Auto-negotiation enabled (%#x)\n", txcw); 11102439e4bfSJean-Christophe PLAGNIOL-VILLARD 11112439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TXCW, txcw); 11122439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 11132439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 11142439e4bfSJean-Christophe PLAGNIOL-VILLARD 11152439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->txcw = txcw; 11162439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(1); 11172439e4bfSJean-Christophe PLAGNIOL-VILLARD 11182439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If we have a signal (the cable is plugged in) then poll for a "Link-Up" 11192439e4bfSJean-Christophe PLAGNIOL-VILLARD * indication in the Device Status Register. Time-out if a link isn't 11202439e4bfSJean-Christophe PLAGNIOL-VILLARD * seen in 500 milliseconds seconds (Auto-negotiation should complete in 11212439e4bfSJean-Christophe PLAGNIOL-VILLARD * less than 500 milliseconds even if the other end is doing it in SW). 11222439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 11232439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { 11242439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Looking for Link\n"); 11252439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { 11262439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(10); 11272439e4bfSJean-Christophe PLAGNIOL-VILLARD status = E1000_READ_REG(hw, STATUS); 11282439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & E1000_STATUS_LU) 11292439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 11302439e4bfSJean-Christophe PLAGNIOL-VILLARD } 11312439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i == (LINK_UP_TIMEOUT / 10)) { 11322439e4bfSJean-Christophe PLAGNIOL-VILLARD /* AutoNeg failed to achieve a link, so we'll call 11332439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_check_for_link. This routine will force the link up if we 11342439e4bfSJean-Christophe PLAGNIOL-VILLARD * detect a signal. This will allow us to communicate with 11352439e4bfSJean-Christophe PLAGNIOL-VILLARD * non-autonegotiating link partners. 11362439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 11372439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Never got a valid link from auto-neg!!!\n"); 11382439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->autoneg_failed = 1; 11392439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_check_for_link(nic); 11402439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 11412439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error while checking for link\n"); 11422439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 11432439e4bfSJean-Christophe PLAGNIOL-VILLARD } 11442439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->autoneg_failed = 0; 11452439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 11462439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->autoneg_failed = 0; 11472439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Valid Link Found\n"); 11482439e4bfSJean-Christophe PLAGNIOL-VILLARD } 11492439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 11502439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("No Signal Detected\n"); 11512439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_NOLINK; 11522439e4bfSJean-Christophe PLAGNIOL-VILLARD } 11532439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 11542439e4bfSJean-Christophe PLAGNIOL-VILLARD } 11552439e4bfSJean-Christophe PLAGNIOL-VILLARD 11562439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 11572439e4bfSJean-Christophe PLAGNIOL-VILLARD * Detects which PHY is present and the speed and duplex 11582439e4bfSJean-Christophe PLAGNIOL-VILLARD * 11592439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 11602439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 11612439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 11622439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_copper_link(struct eth_device *nic) 11632439e4bfSJean-Christophe PLAGNIOL-VILLARD { 11642439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 11652439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 11662439e4bfSJean-Christophe PLAGNIOL-VILLARD int32_t ret_val; 11672439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t i; 11682439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t phy_data; 11692439e4bfSJean-Christophe PLAGNIOL-VILLARD 11702439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 11712439e4bfSJean-Christophe PLAGNIOL-VILLARD 11722439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 11732439e4bfSJean-Christophe PLAGNIOL-VILLARD /* With 82543, we need to force speed and duplex on the MAC equal to what 11742439e4bfSJean-Christophe PLAGNIOL-VILLARD * the PHY speed and duplex configuration is. In addition, we need to 11752439e4bfSJean-Christophe PLAGNIOL-VILLARD * perform a hardware reset on the PHY to take it out of reset. 11762439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 11772439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82543) { 11782439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= E1000_CTRL_SLU; 11792439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 11802439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 11812439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 11822439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= 11832439e4bfSJean-Christophe PLAGNIOL-VILLARD (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); 11842439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 11852439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_phy_hw_reset(hw); 11862439e4bfSJean-Christophe PLAGNIOL-VILLARD } 11872439e4bfSJean-Christophe PLAGNIOL-VILLARD 11882439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Make sure we have a valid PHY */ 11892439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_detect_gig_phy(hw); 11902439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 11912439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error, did not detect valid phy.\n"); 11922439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 11932439e4bfSJean-Christophe PLAGNIOL-VILLARD } 11942439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Phy ID = %x \n", hw->phy_id); 11952439e4bfSJean-Christophe PLAGNIOL-VILLARD 11962439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enable CRS on TX. This must be set for half-duplex operation. */ 11972439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { 11982439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 11992439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 12002439e4bfSJean-Christophe PLAGNIOL-VILLARD } 12012439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; 12022439e4bfSJean-Christophe PLAGNIOL-VILLARD 12032439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 12042439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Options: 12052439e4bfSJean-Christophe PLAGNIOL-VILLARD * MDI/MDI-X = 0 (default) 12062439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0 - Auto for all speeds 12072439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1 - MDI mode 12082439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2 - MDI-X mode 12092439e4bfSJean-Christophe PLAGNIOL-VILLARD * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) 12102439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 12112439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; 12122439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (hw->mdix) { 12132439e4bfSJean-Christophe PLAGNIOL-VILLARD case 1: 12142439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; 12152439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 12162439e4bfSJean-Christophe PLAGNIOL-VILLARD case 2: 12172439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; 12182439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 12192439e4bfSJean-Christophe PLAGNIOL-VILLARD case 3: 12202439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= M88E1000_PSCR_AUTO_X_1000T; 12212439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 12222439e4bfSJean-Christophe PLAGNIOL-VILLARD case 0: 12232439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 12242439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= M88E1000_PSCR_AUTO_X_MODE; 12252439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 12262439e4bfSJean-Christophe PLAGNIOL-VILLARD } 12272439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 12282439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= M88E1000_PSCR_AUTO_X_MODE; 12292439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 12302439e4bfSJean-Christophe PLAGNIOL-VILLARD 12312439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 12322439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Options: 12332439e4bfSJean-Christophe PLAGNIOL-VILLARD * disable_polarity_correction = 0 (default) 12342439e4bfSJean-Christophe PLAGNIOL-VILLARD * Automatic Correction for Reversed Cable Polarity 12352439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0 - Disabled 12362439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1 - Enabled 12372439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 12382439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; 12392439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->disable_polarity_correction == 1) 12402439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; 12412439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 12422439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; 12432439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 12442439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { 12452439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Write Error\n"); 12462439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 12472439e4bfSJean-Christophe PLAGNIOL-VILLARD } 12482439e4bfSJean-Christophe PLAGNIOL-VILLARD 12492439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Force TX_CLK in the Extended PHY Specific Control Register 12502439e4bfSJean-Christophe PLAGNIOL-VILLARD * to 25MHz clock. 12512439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 12522439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { 12532439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 12542439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 12552439e4bfSJean-Christophe PLAGNIOL-VILLARD } 12562439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= M88E1000_EPSCR_TX_CLK_25; 12572439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Configure Master and Slave downshift values */ 12582439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | 12592439e4bfSJean-Christophe PLAGNIOL-VILLARD M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); 12602439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | 12612439e4bfSJean-Christophe PLAGNIOL-VILLARD M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); 12622439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { 12632439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Write Error\n"); 12642439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 12652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 12662439e4bfSJean-Christophe PLAGNIOL-VILLARD 12672439e4bfSJean-Christophe PLAGNIOL-VILLARD /* SW Reset the PHY so all changes take effect */ 12682439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_phy_reset(hw); 12692439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 12702439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error Resetting the PHY\n"); 12712439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 12722439e4bfSJean-Christophe PLAGNIOL-VILLARD } 12732439e4bfSJean-Christophe PLAGNIOL-VILLARD 12742439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Options: 12752439e4bfSJean-Christophe PLAGNIOL-VILLARD * autoneg = 1 (default) 12762439e4bfSJean-Christophe PLAGNIOL-VILLARD * PHY will advertise value(s) parsed from 12772439e4bfSJean-Christophe PLAGNIOL-VILLARD * autoneg_advertised and fc 12782439e4bfSJean-Christophe PLAGNIOL-VILLARD * autoneg = 0 12792439e4bfSJean-Christophe PLAGNIOL-VILLARD * PHY will be set to 10H, 10F, 100H, or 100F 12802439e4bfSJean-Christophe PLAGNIOL-VILLARD * depending on value parsed from forced_speed_duplex. 12812439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 12822439e4bfSJean-Christophe PLAGNIOL-VILLARD 12832439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Is autoneg enabled? This is enabled by default or by software override. 12842439e4bfSJean-Christophe PLAGNIOL-VILLARD * If so, call e1000_phy_setup_autoneg routine to parse the 12852439e4bfSJean-Christophe PLAGNIOL-VILLARD * autoneg_advertised and fc options. If autoneg is NOT enabled, then the 12862439e4bfSJean-Christophe PLAGNIOL-VILLARD * user should have provided a speed/duplex override. If so, then call 12872439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_phy_force_speed_duplex to parse and set this up. 12882439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 12892439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Perform some bounds checking on the hw->autoneg_advertised 12902439e4bfSJean-Christophe PLAGNIOL-VILLARD * parameter. If this variable is zero, then set it to the default. 12912439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 12922439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; 12932439e4bfSJean-Christophe PLAGNIOL-VILLARD 12942439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If autoneg_advertised is zero, we assume it was not defaulted 12952439e4bfSJean-Christophe PLAGNIOL-VILLARD * by the calling code so we set to advertise full capability. 12962439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 12972439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->autoneg_advertised == 0) 12982439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; 12992439e4bfSJean-Christophe PLAGNIOL-VILLARD 13002439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); 13012439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_phy_setup_autoneg(hw); 13022439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 13032439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error Setting up Auto-Negotiation\n"); 13042439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 13052439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13062439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Restarting Auto-Neg\n"); 13072439e4bfSJean-Christophe PLAGNIOL-VILLARD 13082439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Restart auto-negotiation by setting the Auto Neg Enable bit and 13092439e4bfSJean-Christophe PLAGNIOL-VILLARD * the Auto Neg Restart bit in the PHY control register. 13102439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 13112439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) { 13122439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 13132439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 13142439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13152439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); 13162439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) { 13172439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Write Error\n"); 13182439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 13192439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13202439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 13212439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Does the user want to wait for Auto-Neg to complete here, or 13222439e4bfSJean-Christophe PLAGNIOL-VILLARD * check at a later time (for example, callback routine). 13232439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 13242439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->wait_autoneg_complete) { 13252439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_wait_autoneg(hw); 13262439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 13272439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 13282439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Error while waiting for autoneg to complete\n"); 13292439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 13302439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13312439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13322439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 13332439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If we do not wait for autonegtation to complete I 13342439e4bfSJean-Christophe PLAGNIOL-VILLARD * do not see a valid link status. 13352439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 13362439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_wait_autoneg(hw); 13372439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 13382439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error while waiting for autoneg to complete\n"); 13392439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 13402439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13412439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 13422439e4bfSJean-Christophe PLAGNIOL-VILLARD 13432439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check link status. Wait up to 100 microseconds for link to become 13442439e4bfSJean-Christophe PLAGNIOL-VILLARD * valid. 13452439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 13462439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 10; i++) { 13472439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { 13482439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 13492439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 13502439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13512439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { 13522439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 13532439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 13542439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13552439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_data & MII_SR_LINK_STATUS) { 13562439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We have link, so we need to finish the config process: 13572439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1) Set up the MAC to the current PHY speed/duplex 13582439e4bfSJean-Christophe PLAGNIOL-VILLARD * if we are on 82543. If we 13592439e4bfSJean-Christophe PLAGNIOL-VILLARD * are on newer silicon, we only need to configure 13602439e4bfSJean-Christophe PLAGNIOL-VILLARD * collision distance in the Transmit Control Register. 13612439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2) Set up flow control on the MAC to that established with 13622439e4bfSJean-Christophe PLAGNIOL-VILLARD * the link partner. 13632439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 13642439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82544) { 13652439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_config_collision_dist(hw); 13662439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 13672439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_config_mac_to_phy(hw); 13682439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 13692439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 13702439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Error configuring MAC to PHY settings\n"); 13712439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 13722439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13732439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13742439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_config_fc_after_link_up(hw); 13752439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 13762439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error Configuring Flow Control\n"); 13772439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 13782439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13792439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Valid link established!!!\n"); 13802439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 13812439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13822439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10); 13832439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13842439e4bfSJean-Christophe PLAGNIOL-VILLARD 13852439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Unable to establish link!!!\n"); 13862439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_NOLINK; 13872439e4bfSJean-Christophe PLAGNIOL-VILLARD } 13882439e4bfSJean-Christophe PLAGNIOL-VILLARD 13892439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 13902439e4bfSJean-Christophe PLAGNIOL-VILLARD * Configures PHY autoneg and flow control advertisement settings 13912439e4bfSJean-Christophe PLAGNIOL-VILLARD * 13922439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 13932439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 13942439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 13952439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_phy_setup_autoneg(struct e1000_hw *hw) 13962439e4bfSJean-Christophe PLAGNIOL-VILLARD { 13972439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t mii_autoneg_adv_reg; 13982439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t mii_1000t_ctrl_reg; 13992439e4bfSJean-Christophe PLAGNIOL-VILLARD 14002439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 14012439e4bfSJean-Christophe PLAGNIOL-VILLARD 14022439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the MII Auto-Neg Advertisement Register (Address 4). */ 14032439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg) < 0) { 14042439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 14052439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 14062439e4bfSJean-Christophe PLAGNIOL-VILLARD } 14072439e4bfSJean-Christophe PLAGNIOL-VILLARD 14082439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the MII 1000Base-T Control Register (Address 9). */ 14092439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg) < 0) { 14102439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 14112439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 14122439e4bfSJean-Christophe PLAGNIOL-VILLARD } 14132439e4bfSJean-Christophe PLAGNIOL-VILLARD 14142439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Need to parse both autoneg_advertised and fc and set up 14152439e4bfSJean-Christophe PLAGNIOL-VILLARD * the appropriate PHY registers. First we will parse for 14162439e4bfSJean-Christophe PLAGNIOL-VILLARD * autoneg_advertised software override. Since we can advertise 14172439e4bfSJean-Christophe PLAGNIOL-VILLARD * a plethora of combinations, we need to check each bit 14182439e4bfSJean-Christophe PLAGNIOL-VILLARD * individually. 14192439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 14202439e4bfSJean-Christophe PLAGNIOL-VILLARD 14212439e4bfSJean-Christophe PLAGNIOL-VILLARD /* First we clear all the 10/100 mb speed bits in the Auto-Neg 14222439e4bfSJean-Christophe PLAGNIOL-VILLARD * Advertisement Register (Address 4) and the 1000 mb speed bits in 14232439e4bfSJean-Christophe PLAGNIOL-VILLARD * the 1000Base-T Control Register (Address 9). 14242439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 14252439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg &= ~REG4_SPEED_MASK; 14262439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; 14272439e4bfSJean-Christophe PLAGNIOL-VILLARD 14282439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("autoneg_advertised %x\n", hw->autoneg_advertised); 14292439e4bfSJean-Christophe PLAGNIOL-VILLARD 14302439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Do we want to advertise 10 Mb Half Duplex? */ 14312439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->autoneg_advertised & ADVERTISE_10_HALF) { 14322439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Advertise 10mb Half duplex\n"); 14332439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; 14342439e4bfSJean-Christophe PLAGNIOL-VILLARD } 14352439e4bfSJean-Christophe PLAGNIOL-VILLARD 14362439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Do we want to advertise 10 Mb Full Duplex? */ 14372439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->autoneg_advertised & ADVERTISE_10_FULL) { 14382439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Advertise 10mb Full duplex\n"); 14392439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; 14402439e4bfSJean-Christophe PLAGNIOL-VILLARD } 14412439e4bfSJean-Christophe PLAGNIOL-VILLARD 14422439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Do we want to advertise 100 Mb Half Duplex? */ 14432439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->autoneg_advertised & ADVERTISE_100_HALF) { 14442439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Advertise 100mb Half duplex\n"); 14452439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; 14462439e4bfSJean-Christophe PLAGNIOL-VILLARD } 14472439e4bfSJean-Christophe PLAGNIOL-VILLARD 14482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Do we want to advertise 100 Mb Full Duplex? */ 14492439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->autoneg_advertised & ADVERTISE_100_FULL) { 14502439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Advertise 100mb Full duplex\n"); 14512439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; 14522439e4bfSJean-Christophe PLAGNIOL-VILLARD } 14532439e4bfSJean-Christophe PLAGNIOL-VILLARD 14542439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ 14552439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->autoneg_advertised & ADVERTISE_1000_HALF) { 14562439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 14572439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Advertise 1000mb Half duplex requested, request denied!\n"); 14582439e4bfSJean-Christophe PLAGNIOL-VILLARD } 14592439e4bfSJean-Christophe PLAGNIOL-VILLARD 14602439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Do we want to advertise 1000 Mb Full Duplex? */ 14612439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->autoneg_advertised & ADVERTISE_1000_FULL) { 14622439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Advertise 1000mb Full duplex\n"); 14632439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; 14642439e4bfSJean-Christophe PLAGNIOL-VILLARD } 14652439e4bfSJean-Christophe PLAGNIOL-VILLARD 14662439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check for a software override of the flow control settings, and 14672439e4bfSJean-Christophe PLAGNIOL-VILLARD * setup the PHY advertisement registers accordingly. If 14682439e4bfSJean-Christophe PLAGNIOL-VILLARD * auto-negotiation is enabled, then software will have to set the 14692439e4bfSJean-Christophe PLAGNIOL-VILLARD * "PAUSE" bits to the correct value in the Auto-Negotiation 14702439e4bfSJean-Christophe PLAGNIOL-VILLARD * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation. 14712439e4bfSJean-Christophe PLAGNIOL-VILLARD * 14722439e4bfSJean-Christophe PLAGNIOL-VILLARD * The possible values of the "fc" parameter are: 14732439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0: Flow control is completely disabled 14742439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1: Rx flow control is enabled (we can receive pause frames 14752439e4bfSJean-Christophe PLAGNIOL-VILLARD * but not send pause frames). 14762439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2: Tx flow control is enabled (we can send pause frames 14772439e4bfSJean-Christophe PLAGNIOL-VILLARD * but we do not support receiving pause frames). 14782439e4bfSJean-Christophe PLAGNIOL-VILLARD * 3: Both Rx and TX flow control (symmetric) are enabled. 14792439e4bfSJean-Christophe PLAGNIOL-VILLARD * other: No software override. The flow control configuration 14802439e4bfSJean-Christophe PLAGNIOL-VILLARD * in the EEPROM is used. 14812439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 14822439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (hw->fc) { 14832439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_none: /* 0 */ 14842439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Flow control (RX & TX) is completely disabled by a 14852439e4bfSJean-Christophe PLAGNIOL-VILLARD * software over-ride. 14862439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 14872439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 14882439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 14892439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_rx_pause: /* 1 */ 14902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RX Flow control is enabled, and TX Flow control is 14912439e4bfSJean-Christophe PLAGNIOL-VILLARD * disabled, by a software over-ride. 14922439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 14932439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Since there really isn't a way to advertise that we are 14942439e4bfSJean-Christophe PLAGNIOL-VILLARD * capable of RX Pause ONLY, we will advertise that we 14952439e4bfSJean-Christophe PLAGNIOL-VILLARD * support both symmetric and asymmetric RX PAUSE. Later 14962439e4bfSJean-Christophe PLAGNIOL-VILLARD * (in e1000_config_fc_after_link_up) we will disable the 14972439e4bfSJean-Christophe PLAGNIOL-VILLARD *hw's ability to send PAUSE frames. 14982439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 14992439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 15002439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 15012439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_tx_pause: /* 2 */ 15022439e4bfSJean-Christophe PLAGNIOL-VILLARD /* TX Flow control is enabled, and RX Flow control is 15032439e4bfSJean-Christophe PLAGNIOL-VILLARD * disabled, by a software over-ride. 15042439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 15052439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; 15062439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; 15072439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 15082439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_full: /* 3 */ 15092439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Flow control (both RX and TX) is enabled by a software 15102439e4bfSJean-Christophe PLAGNIOL-VILLARD * over-ride. 15112439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 15122439e4bfSJean-Christophe PLAGNIOL-VILLARD mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 15132439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 15142439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 15152439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Flow control param set incorrectly\n"); 15162439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_CONFIG; 15172439e4bfSJean-Christophe PLAGNIOL-VILLARD } 15182439e4bfSJean-Christophe PLAGNIOL-VILLARD 15192439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg) < 0) { 15202439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Write Error\n"); 15212439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 15222439e4bfSJean-Christophe PLAGNIOL-VILLARD } 15232439e4bfSJean-Christophe PLAGNIOL-VILLARD 15242439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); 15252439e4bfSJean-Christophe PLAGNIOL-VILLARD 15262439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg) < 0) { 15272439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Write Error\n"); 15282439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 15292439e4bfSJean-Christophe PLAGNIOL-VILLARD } 15302439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 15312439e4bfSJean-Christophe PLAGNIOL-VILLARD } 15322439e4bfSJean-Christophe PLAGNIOL-VILLARD 15332439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 15342439e4bfSJean-Christophe PLAGNIOL-VILLARD * Sets the collision distance in the Transmit Control register 15352439e4bfSJean-Christophe PLAGNIOL-VILLARD * 15362439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 15372439e4bfSJean-Christophe PLAGNIOL-VILLARD * 15382439e4bfSJean-Christophe PLAGNIOL-VILLARD * Link should have been established previously. Reads the speed and duplex 15392439e4bfSJean-Christophe PLAGNIOL-VILLARD * information from the Device Status register. 15402439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 15412439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 15422439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_config_collision_dist(struct e1000_hw *hw) 15432439e4bfSJean-Christophe PLAGNIOL-VILLARD { 15442439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t tctl; 15452439e4bfSJean-Christophe PLAGNIOL-VILLARD 15462439e4bfSJean-Christophe PLAGNIOL-VILLARD tctl = E1000_READ_REG(hw, TCTL); 15472439e4bfSJean-Christophe PLAGNIOL-VILLARD 15482439e4bfSJean-Christophe PLAGNIOL-VILLARD tctl &= ~E1000_TCTL_COLD; 15492439e4bfSJean-Christophe PLAGNIOL-VILLARD tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; 15502439e4bfSJean-Christophe PLAGNIOL-VILLARD 15512439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TCTL, tctl); 15522439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 15532439e4bfSJean-Christophe PLAGNIOL-VILLARD } 15542439e4bfSJean-Christophe PLAGNIOL-VILLARD 15552439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 15562439e4bfSJean-Christophe PLAGNIOL-VILLARD * Sets MAC speed and duplex settings to reflect the those in the PHY 15572439e4bfSJean-Christophe PLAGNIOL-VILLARD * 15582439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 15592439e4bfSJean-Christophe PLAGNIOL-VILLARD * mii_reg - data to write to the MII control register 15602439e4bfSJean-Christophe PLAGNIOL-VILLARD * 15612439e4bfSJean-Christophe PLAGNIOL-VILLARD * The contents of the PHY register containing the needed information need to 15622439e4bfSJean-Christophe PLAGNIOL-VILLARD * be passed in. 15632439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 15642439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 15652439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_config_mac_to_phy(struct e1000_hw *hw) 15662439e4bfSJean-Christophe PLAGNIOL-VILLARD { 15672439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 15682439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t phy_data; 15692439e4bfSJean-Christophe PLAGNIOL-VILLARD 15702439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 15712439e4bfSJean-Christophe PLAGNIOL-VILLARD 15722439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the Device Control Register and set the bits to Force Speed 15732439e4bfSJean-Christophe PLAGNIOL-VILLARD * and Duplex. 15742439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 15752439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 15762439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 15772439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); 15782439e4bfSJean-Christophe PLAGNIOL-VILLARD 15792439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set up duplex in the Device Control and Transmit Control 15802439e4bfSJean-Christophe PLAGNIOL-VILLARD * registers depending on negotiated values. 15812439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 15822439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { 15832439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 15842439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 15852439e4bfSJean-Christophe PLAGNIOL-VILLARD } 15862439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_data & M88E1000_PSSR_DPLX) 15872439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= E1000_CTRL_FD; 15882439e4bfSJean-Christophe PLAGNIOL-VILLARD else 15892439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= ~E1000_CTRL_FD; 15902439e4bfSJean-Christophe PLAGNIOL-VILLARD 15912439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_config_collision_dist(hw); 15922439e4bfSJean-Christophe PLAGNIOL-VILLARD 15932439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set up speed in the Device Control register depending on 15942439e4bfSJean-Christophe PLAGNIOL-VILLARD * negotiated values. 15952439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 15962439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) 15972439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= E1000_CTRL_SPD_1000; 15982439e4bfSJean-Christophe PLAGNIOL-VILLARD else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) 15992439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= E1000_CTRL_SPD_100; 16002439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Write the configured values back to the Device Control Reg. */ 16012439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 16022439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 16032439e4bfSJean-Christophe PLAGNIOL-VILLARD } 16042439e4bfSJean-Christophe PLAGNIOL-VILLARD 16052439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 16062439e4bfSJean-Christophe PLAGNIOL-VILLARD * Forces the MAC's flow control settings. 16072439e4bfSJean-Christophe PLAGNIOL-VILLARD * 16082439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 16092439e4bfSJean-Christophe PLAGNIOL-VILLARD * 16102439e4bfSJean-Christophe PLAGNIOL-VILLARD * Sets the TFCE and RFCE bits in the device control register to reflect 16112439e4bfSJean-Christophe PLAGNIOL-VILLARD * the adapter settings. TFCE and RFCE need to be explicitly set by 16122439e4bfSJean-Christophe PLAGNIOL-VILLARD * software when a Copper PHY is used because autonegotiation is managed 16132439e4bfSJean-Christophe PLAGNIOL-VILLARD * by the PHY rather than the MAC. Software must also configure these 16142439e4bfSJean-Christophe PLAGNIOL-VILLARD * bits when link is forced on a fiber connection. 16152439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 16162439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 16172439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_force_mac_fc(struct e1000_hw *hw) 16182439e4bfSJean-Christophe PLAGNIOL-VILLARD { 16192439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 16202439e4bfSJean-Christophe PLAGNIOL-VILLARD 16212439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 16222439e4bfSJean-Christophe PLAGNIOL-VILLARD 16232439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Get the current configuration of the Device Control Register */ 16242439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 16252439e4bfSJean-Christophe PLAGNIOL-VILLARD 16262439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Because we didn't get link via the internal auto-negotiation 16272439e4bfSJean-Christophe PLAGNIOL-VILLARD * mechanism (we either forced link or we got link via PHY 16282439e4bfSJean-Christophe PLAGNIOL-VILLARD * auto-neg), we have to manually enable/disable transmit an 16292439e4bfSJean-Christophe PLAGNIOL-VILLARD * receive flow control. 16302439e4bfSJean-Christophe PLAGNIOL-VILLARD * 16312439e4bfSJean-Christophe PLAGNIOL-VILLARD * The "Case" statement below enables/disable flow control 16322439e4bfSJean-Christophe PLAGNIOL-VILLARD * according to the "hw->fc" parameter. 16332439e4bfSJean-Christophe PLAGNIOL-VILLARD * 16342439e4bfSJean-Christophe PLAGNIOL-VILLARD * The possible values of the "fc" parameter are: 16352439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0: Flow control is completely disabled 16362439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1: Rx flow control is enabled (we can receive pause 16372439e4bfSJean-Christophe PLAGNIOL-VILLARD * frames but not send pause frames). 16382439e4bfSJean-Christophe PLAGNIOL-VILLARD * 2: Tx flow control is enabled (we can send pause frames 16392439e4bfSJean-Christophe PLAGNIOL-VILLARD * frames but we do not receive pause frames). 16402439e4bfSJean-Christophe PLAGNIOL-VILLARD * 3: Both Rx and TX flow control (symmetric) is enabled. 16412439e4bfSJean-Christophe PLAGNIOL-VILLARD * other: No other values should be possible at this point. 16422439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 16432439e4bfSJean-Christophe PLAGNIOL-VILLARD 16442439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (hw->fc) { 16452439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_none: 16462439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); 16472439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 16482439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_rx_pause: 16492439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= (~E1000_CTRL_TFCE); 16502439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= E1000_CTRL_RFCE; 16512439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 16522439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_tx_pause: 16532439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= (~E1000_CTRL_RFCE); 16542439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= E1000_CTRL_TFCE; 16552439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 16562439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_fc_full: 16572439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); 16582439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 16592439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 16602439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Flow control param set incorrectly\n"); 16612439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_CONFIG; 16622439e4bfSJean-Christophe PLAGNIOL-VILLARD } 16632439e4bfSJean-Christophe PLAGNIOL-VILLARD 16642439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disable TX Flow Control for 82542 (rev 2.0) */ 16652439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type == e1000_82542_rev2_0) 16662439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= (~E1000_CTRL_TFCE); 16672439e4bfSJean-Christophe PLAGNIOL-VILLARD 16682439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 16692439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 16702439e4bfSJean-Christophe PLAGNIOL-VILLARD } 16712439e4bfSJean-Christophe PLAGNIOL-VILLARD 16722439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 16732439e4bfSJean-Christophe PLAGNIOL-VILLARD * Configures flow control settings after link is established 16742439e4bfSJean-Christophe PLAGNIOL-VILLARD * 16752439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 16762439e4bfSJean-Christophe PLAGNIOL-VILLARD * 16772439e4bfSJean-Christophe PLAGNIOL-VILLARD * Should be called immediately after a valid link has been established. 16782439e4bfSJean-Christophe PLAGNIOL-VILLARD * Forces MAC flow control settings if link was forced. When in MII/GMII mode 16792439e4bfSJean-Christophe PLAGNIOL-VILLARD * and autonegotiation is enabled, the MAC flow control settings will be set 16802439e4bfSJean-Christophe PLAGNIOL-VILLARD * based on the flow control negotiated by the PHY. In TBI mode, the TFCE 16812439e4bfSJean-Christophe PLAGNIOL-VILLARD * and RFCE bits will be automaticaly set to the negotiated flow control mode. 16822439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 16832439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 16842439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_config_fc_after_link_up(struct e1000_hw *hw) 16852439e4bfSJean-Christophe PLAGNIOL-VILLARD { 16862439e4bfSJean-Christophe PLAGNIOL-VILLARD int32_t ret_val; 16872439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t mii_status_reg; 16882439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t mii_nway_adv_reg; 16892439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t mii_nway_lp_ability_reg; 16902439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t speed; 16912439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t duplex; 16922439e4bfSJean-Christophe PLAGNIOL-VILLARD 16932439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 16942439e4bfSJean-Christophe PLAGNIOL-VILLARD 16952439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check for the case where we have fiber media and auto-neg failed 16962439e4bfSJean-Christophe PLAGNIOL-VILLARD * so we had to force link. In this case, we need to force the 16972439e4bfSJean-Christophe PLAGNIOL-VILLARD * configuration of the MAC to match the "fc" parameter. 16982439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 16992439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) { 17002439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_force_mac_fc(hw); 17012439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 17022439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error forcing flow control settings\n"); 17032439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 17042439e4bfSJean-Christophe PLAGNIOL-VILLARD } 17052439e4bfSJean-Christophe PLAGNIOL-VILLARD } 17062439e4bfSJean-Christophe PLAGNIOL-VILLARD 17072439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check for the case where we have copper media and auto-neg is 17082439e4bfSJean-Christophe PLAGNIOL-VILLARD * enabled. In this case, we need to check and see if Auto-Neg 17092439e4bfSJean-Christophe PLAGNIOL-VILLARD * has completed, and if so, how the PHY and link partner has 17102439e4bfSJean-Christophe PLAGNIOL-VILLARD * flow control configured. 17112439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 17122439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->media_type == e1000_media_type_copper) { 17132439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the MII Status Register and check to see if AutoNeg 17142439e4bfSJean-Christophe PLAGNIOL-VILLARD * has completed. We read this twice because this reg has 17152439e4bfSJean-Christophe PLAGNIOL-VILLARD * some "sticky" (latched) bits. 17162439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 17172439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { 17182439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error \n"); 17192439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 17202439e4bfSJean-Christophe PLAGNIOL-VILLARD } 17212439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { 17222439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error \n"); 17232439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 17242439e4bfSJean-Christophe PLAGNIOL-VILLARD } 17252439e4bfSJean-Christophe PLAGNIOL-VILLARD 17262439e4bfSJean-Christophe PLAGNIOL-VILLARD if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) { 17272439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The AutoNeg process has completed, so we now need to 17282439e4bfSJean-Christophe PLAGNIOL-VILLARD * read both the Auto Negotiation Advertisement Register 17292439e4bfSJean-Christophe PLAGNIOL-VILLARD * (Address 4) and the Auto_Negotiation Base Page Ability 17302439e4bfSJean-Christophe PLAGNIOL-VILLARD * Register (Address 5) to determine how flow control was 17312439e4bfSJean-Christophe PLAGNIOL-VILLARD * negotiated. 17322439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 17332439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg 17342439e4bfSJean-Christophe PLAGNIOL-VILLARD (hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg) < 0) { 17352439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 17362439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 17372439e4bfSJean-Christophe PLAGNIOL-VILLARD } 17382439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg 17392439e4bfSJean-Christophe PLAGNIOL-VILLARD (hw, PHY_LP_ABILITY, 17402439e4bfSJean-Christophe PLAGNIOL-VILLARD &mii_nway_lp_ability_reg) < 0) { 17412439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 17422439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 17432439e4bfSJean-Christophe PLAGNIOL-VILLARD } 17442439e4bfSJean-Christophe PLAGNIOL-VILLARD 17452439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Two bits in the Auto Negotiation Advertisement Register 17462439e4bfSJean-Christophe PLAGNIOL-VILLARD * (Address 4) and two bits in the Auto Negotiation Base 17472439e4bfSJean-Christophe PLAGNIOL-VILLARD * Page Ability Register (Address 5) determine flow control 17482439e4bfSJean-Christophe PLAGNIOL-VILLARD * for both the PHY and the link partner. The following 17492439e4bfSJean-Christophe PLAGNIOL-VILLARD * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, 17502439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1999, describes these PAUSE resolution bits and how flow 17512439e4bfSJean-Christophe PLAGNIOL-VILLARD * control is determined based upon these settings. 17522439e4bfSJean-Christophe PLAGNIOL-VILLARD * NOTE: DC = Don't Care 17532439e4bfSJean-Christophe PLAGNIOL-VILLARD * 17542439e4bfSJean-Christophe PLAGNIOL-VILLARD * LOCAL DEVICE | LINK PARTNER 17552439e4bfSJean-Christophe PLAGNIOL-VILLARD * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution 17562439e4bfSJean-Christophe PLAGNIOL-VILLARD *-------|---------|-------|---------|-------------------- 17572439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0 | 0 | DC | DC | e1000_fc_none 17582439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0 | 1 | 0 | DC | e1000_fc_none 17592439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0 | 1 | 1 | 0 | e1000_fc_none 17602439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0 | 1 | 1 | 1 | e1000_fc_tx_pause 17612439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1 | 0 | 0 | DC | e1000_fc_none 17622439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1 | DC | 1 | DC | e1000_fc_full 17632439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1 | 1 | 0 | 0 | e1000_fc_none 17642439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1 | 1 | 0 | 1 | e1000_fc_rx_pause 17652439e4bfSJean-Christophe PLAGNIOL-VILLARD * 17662439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 17672439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Are both PAUSE bits set to 1? If so, this implies 17682439e4bfSJean-Christophe PLAGNIOL-VILLARD * Symmetric Flow Control is enabled at both ends. The 17692439e4bfSJean-Christophe PLAGNIOL-VILLARD * ASM_DIR bits are irrelevant per the spec. 17702439e4bfSJean-Christophe PLAGNIOL-VILLARD * 17712439e4bfSJean-Christophe PLAGNIOL-VILLARD * For Symmetric Flow Control: 17722439e4bfSJean-Christophe PLAGNIOL-VILLARD * 17732439e4bfSJean-Christophe PLAGNIOL-VILLARD * LOCAL DEVICE | LINK PARTNER 17742439e4bfSJean-Christophe PLAGNIOL-VILLARD * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result 17752439e4bfSJean-Christophe PLAGNIOL-VILLARD *-------|---------|-------|---------|-------------------- 17762439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1 | DC | 1 | DC | e1000_fc_full 17772439e4bfSJean-Christophe PLAGNIOL-VILLARD * 17782439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 17792439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && 17802439e4bfSJean-Christophe PLAGNIOL-VILLARD (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { 17812439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Now we need to check if the user selected RX ONLY 17822439e4bfSJean-Christophe PLAGNIOL-VILLARD * of pause frames. In this case, we had to advertise 17832439e4bfSJean-Christophe PLAGNIOL-VILLARD * FULL flow control because we could not advertise RX 17842439e4bfSJean-Christophe PLAGNIOL-VILLARD * ONLY. Hence, we must now check to see if we need to 17852439e4bfSJean-Christophe PLAGNIOL-VILLARD * turn OFF the TRANSMISSION of PAUSE frames. 17862439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 17872439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->original_fc == e1000_fc_full) { 17882439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_full; 17892439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Flow Control = FULL.\r\n"); 17902439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 17912439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_rx_pause; 17922439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 17932439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Flow Control = RX PAUSE frames only.\r\n"); 17942439e4bfSJean-Christophe PLAGNIOL-VILLARD } 17952439e4bfSJean-Christophe PLAGNIOL-VILLARD } 17962439e4bfSJean-Christophe PLAGNIOL-VILLARD /* For receiving PAUSE frames ONLY. 17972439e4bfSJean-Christophe PLAGNIOL-VILLARD * 17982439e4bfSJean-Christophe PLAGNIOL-VILLARD * LOCAL DEVICE | LINK PARTNER 17992439e4bfSJean-Christophe PLAGNIOL-VILLARD * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result 18002439e4bfSJean-Christophe PLAGNIOL-VILLARD *-------|---------|-------|---------|-------------------- 18012439e4bfSJean-Christophe PLAGNIOL-VILLARD * 0 | 1 | 1 | 1 | e1000_fc_tx_pause 18022439e4bfSJean-Christophe PLAGNIOL-VILLARD * 18032439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 18042439e4bfSJean-Christophe PLAGNIOL-VILLARD else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && 18052439e4bfSJean-Christophe PLAGNIOL-VILLARD (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && 18062439e4bfSJean-Christophe PLAGNIOL-VILLARD (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && 18072439e4bfSJean-Christophe PLAGNIOL-VILLARD (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) 18082439e4bfSJean-Christophe PLAGNIOL-VILLARD { 18092439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_tx_pause; 18102439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 18112439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Flow Control = TX PAUSE frames only.\r\n"); 18122439e4bfSJean-Christophe PLAGNIOL-VILLARD } 18132439e4bfSJean-Christophe PLAGNIOL-VILLARD /* For transmitting PAUSE frames ONLY. 18142439e4bfSJean-Christophe PLAGNIOL-VILLARD * 18152439e4bfSJean-Christophe PLAGNIOL-VILLARD * LOCAL DEVICE | LINK PARTNER 18162439e4bfSJean-Christophe PLAGNIOL-VILLARD * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result 18172439e4bfSJean-Christophe PLAGNIOL-VILLARD *-------|---------|-------|---------|-------------------- 18182439e4bfSJean-Christophe PLAGNIOL-VILLARD * 1 | 1 | 0 | 1 | e1000_fc_rx_pause 18192439e4bfSJean-Christophe PLAGNIOL-VILLARD * 18202439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 18212439e4bfSJean-Christophe PLAGNIOL-VILLARD else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && 18222439e4bfSJean-Christophe PLAGNIOL-VILLARD (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && 18232439e4bfSJean-Christophe PLAGNIOL-VILLARD !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && 18242439e4bfSJean-Christophe PLAGNIOL-VILLARD (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) 18252439e4bfSJean-Christophe PLAGNIOL-VILLARD { 18262439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_rx_pause; 18272439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 18282439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Flow Control = RX PAUSE frames only.\r\n"); 18292439e4bfSJean-Christophe PLAGNIOL-VILLARD } 18302439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Per the IEEE spec, at this point flow control should be 18312439e4bfSJean-Christophe PLAGNIOL-VILLARD * disabled. However, we want to consider that we could 18322439e4bfSJean-Christophe PLAGNIOL-VILLARD * be connected to a legacy switch that doesn't advertise 18332439e4bfSJean-Christophe PLAGNIOL-VILLARD * desired flow control, but can be forced on the link 18342439e4bfSJean-Christophe PLAGNIOL-VILLARD * partner. So if we advertised no flow control, that is 18352439e4bfSJean-Christophe PLAGNIOL-VILLARD * what we will resolve to. If we advertised some kind of 18362439e4bfSJean-Christophe PLAGNIOL-VILLARD * receive capability (Rx Pause Only or Full Flow Control) 18372439e4bfSJean-Christophe PLAGNIOL-VILLARD * and the link partner advertised none, we will configure 18382439e4bfSJean-Christophe PLAGNIOL-VILLARD * ourselves to enable Rx Flow Control only. We can do 18392439e4bfSJean-Christophe PLAGNIOL-VILLARD * this safely for two reasons: If the link partner really 18402439e4bfSJean-Christophe PLAGNIOL-VILLARD * didn't want flow control enabled, and we enable Rx, no 18412439e4bfSJean-Christophe PLAGNIOL-VILLARD * harm done since we won't be receiving any PAUSE frames 18422439e4bfSJean-Christophe PLAGNIOL-VILLARD * anyway. If the intent on the link partner was to have 18432439e4bfSJean-Christophe PLAGNIOL-VILLARD * flow control enabled, then by us enabling RX only, we 18442439e4bfSJean-Christophe PLAGNIOL-VILLARD * can at least receive pause frames and process them. 18452439e4bfSJean-Christophe PLAGNIOL-VILLARD * This is a good idea because in most cases, since we are 18462439e4bfSJean-Christophe PLAGNIOL-VILLARD * predominantly a server NIC, more times than not we will 18472439e4bfSJean-Christophe PLAGNIOL-VILLARD * be asked to delay transmission of packets than asking 18482439e4bfSJean-Christophe PLAGNIOL-VILLARD * our link partner to pause transmission of frames. 18492439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 18502439e4bfSJean-Christophe PLAGNIOL-VILLARD else if (hw->original_fc == e1000_fc_none || 18512439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->original_fc == e1000_fc_tx_pause) { 18522439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_none; 18532439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Flow Control = NONE.\r\n"); 18542439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 18552439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_rx_pause; 18562439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 18572439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Flow Control = RX PAUSE frames only.\r\n"); 18582439e4bfSJean-Christophe PLAGNIOL-VILLARD } 18592439e4bfSJean-Christophe PLAGNIOL-VILLARD 18602439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Now we need to do one last check... If we auto- 18612439e4bfSJean-Christophe PLAGNIOL-VILLARD * negotiated to HALF DUPLEX, flow control should not be 18622439e4bfSJean-Christophe PLAGNIOL-VILLARD * enabled per IEEE 802.3 spec. 18632439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 18642439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_get_speed_and_duplex(hw, &speed, &duplex); 18652439e4bfSJean-Christophe PLAGNIOL-VILLARD 18662439e4bfSJean-Christophe PLAGNIOL-VILLARD if (duplex == HALF_DUPLEX) 18672439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_none; 18682439e4bfSJean-Christophe PLAGNIOL-VILLARD 18692439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Now we call a subroutine to actually force the MAC 18702439e4bfSJean-Christophe PLAGNIOL-VILLARD * controller to use the correct flow control settings. 18712439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 18722439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_force_mac_fc(hw); 18732439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 18742439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 18752439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Error forcing flow control settings\n"); 18762439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 18772439e4bfSJean-Christophe PLAGNIOL-VILLARD } 18782439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 18792439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 18802439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Copper PHY and Auto Neg has not completed.\r\n"); 18812439e4bfSJean-Christophe PLAGNIOL-VILLARD } 18822439e4bfSJean-Christophe PLAGNIOL-VILLARD } 18832439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 18842439e4bfSJean-Christophe PLAGNIOL-VILLARD } 18852439e4bfSJean-Christophe PLAGNIOL-VILLARD 18862439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 18872439e4bfSJean-Christophe PLAGNIOL-VILLARD * Checks to see if the link status of the hardware has changed. 18882439e4bfSJean-Christophe PLAGNIOL-VILLARD * 18892439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 18902439e4bfSJean-Christophe PLAGNIOL-VILLARD * 18912439e4bfSJean-Christophe PLAGNIOL-VILLARD * Called by any function that needs to check the link status of the adapter. 18922439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 18932439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 18942439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_check_for_link(struct eth_device *nic) 18952439e4bfSJean-Christophe PLAGNIOL-VILLARD { 18962439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 18972439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t rxcw; 18982439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 18992439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t status; 19002439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t rctl; 19012439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t signal; 19022439e4bfSJean-Christophe PLAGNIOL-VILLARD int32_t ret_val; 19032439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t phy_data; 19042439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t lp_capability; 19052439e4bfSJean-Christophe PLAGNIOL-VILLARD 19062439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 19072439e4bfSJean-Christophe PLAGNIOL-VILLARD 19082439e4bfSJean-Christophe PLAGNIOL-VILLARD /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be 19092439e4bfSJean-Christophe PLAGNIOL-VILLARD * set when the optics detect a signal. On older adapters, it will be 19102439e4bfSJean-Christophe PLAGNIOL-VILLARD * cleared when there is a signal 19112439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 19122439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 19132439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((hw->mac_type > e1000_82544) && !(ctrl & E1000_CTRL_ILOS)) 19142439e4bfSJean-Christophe PLAGNIOL-VILLARD signal = E1000_CTRL_SWDPIN1; 19152439e4bfSJean-Christophe PLAGNIOL-VILLARD else 19162439e4bfSJean-Christophe PLAGNIOL-VILLARD signal = 0; 19172439e4bfSJean-Christophe PLAGNIOL-VILLARD 19182439e4bfSJean-Christophe PLAGNIOL-VILLARD status = E1000_READ_REG(hw, STATUS); 19192439e4bfSJean-Christophe PLAGNIOL-VILLARD rxcw = E1000_READ_REG(hw, RXCW); 19202439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("ctrl: %#08x status %#08x rxcw %#08x\n", ctrl, status, rxcw); 19212439e4bfSJean-Christophe PLAGNIOL-VILLARD 19222439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If we have a copper PHY then we only want to go out to the PHY 19232439e4bfSJean-Christophe PLAGNIOL-VILLARD * registers to see if Auto-Neg has completed and/or if our link 19242439e4bfSJean-Christophe PLAGNIOL-VILLARD * status has changed. The get_link_status flag will be set if we 19252439e4bfSJean-Christophe PLAGNIOL-VILLARD * receive a Link Status Change interrupt or we have Rx Sequence 19262439e4bfSJean-Christophe PLAGNIOL-VILLARD * Errors. 19272439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 19282439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) { 19292439e4bfSJean-Christophe PLAGNIOL-VILLARD /* First we want to see if the MII Status Register reports 19302439e4bfSJean-Christophe PLAGNIOL-VILLARD * link. If so, then we want to get the current speed/duplex 19312439e4bfSJean-Christophe PLAGNIOL-VILLARD * of the PHY. 19322439e4bfSJean-Christophe PLAGNIOL-VILLARD * Read the register twice since the link bit is sticky. 19332439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 19342439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { 19352439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 19362439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 19372439e4bfSJean-Christophe PLAGNIOL-VILLARD } 19382439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { 19392439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 19402439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 19412439e4bfSJean-Christophe PLAGNIOL-VILLARD } 19422439e4bfSJean-Christophe PLAGNIOL-VILLARD 19432439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_data & MII_SR_LINK_STATUS) { 19442439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->get_link_status = FALSE; 19452439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 19462439e4bfSJean-Christophe PLAGNIOL-VILLARD /* No link detected */ 19472439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_NOLINK; 19482439e4bfSJean-Christophe PLAGNIOL-VILLARD } 19492439e4bfSJean-Christophe PLAGNIOL-VILLARD 19502439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We have a M88E1000 PHY and Auto-Neg is enabled. If we 19512439e4bfSJean-Christophe PLAGNIOL-VILLARD * have Si on board that is 82544 or newer, Auto 19522439e4bfSJean-Christophe PLAGNIOL-VILLARD * Speed Detection takes care of MAC speed/duplex 19532439e4bfSJean-Christophe PLAGNIOL-VILLARD * configuration. So we only need to configure Collision 19542439e4bfSJean-Christophe PLAGNIOL-VILLARD * Distance in the MAC. Otherwise, we need to force 19552439e4bfSJean-Christophe PLAGNIOL-VILLARD * speed/duplex on the MAC to the current PHY speed/duplex 19562439e4bfSJean-Christophe PLAGNIOL-VILLARD * settings. 19572439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 19582439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82544) 19592439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_config_collision_dist(hw); 19602439e4bfSJean-Christophe PLAGNIOL-VILLARD else { 19612439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_config_mac_to_phy(hw); 19622439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 19632439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 19642439e4bfSJean-Christophe PLAGNIOL-VILLARD ("Error configuring MAC to PHY settings\n"); 19652439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 19662439e4bfSJean-Christophe PLAGNIOL-VILLARD } 19672439e4bfSJean-Christophe PLAGNIOL-VILLARD } 19682439e4bfSJean-Christophe PLAGNIOL-VILLARD 19692439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Configure Flow Control now that Auto-Neg has completed. First, we 19702439e4bfSJean-Christophe PLAGNIOL-VILLARD * need to restore the desired flow control settings because we may 19712439e4bfSJean-Christophe PLAGNIOL-VILLARD * have had to re-autoneg with a different link partner. 19722439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 19732439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_config_fc_after_link_up(hw); 19742439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 19752439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error configuring flow control\n"); 19762439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 19772439e4bfSJean-Christophe PLAGNIOL-VILLARD } 19782439e4bfSJean-Christophe PLAGNIOL-VILLARD 19792439e4bfSJean-Christophe PLAGNIOL-VILLARD /* At this point we know that we are on copper and we have 19802439e4bfSJean-Christophe PLAGNIOL-VILLARD * auto-negotiated link. These are conditions for checking the link 19812439e4bfSJean-Christophe PLAGNIOL-VILLARD * parter capability register. We use the link partner capability to 19822439e4bfSJean-Christophe PLAGNIOL-VILLARD * determine if TBI Compatibility needs to be turned on or off. If 19832439e4bfSJean-Christophe PLAGNIOL-VILLARD * the link partner advertises any speed in addition to Gigabit, then 19842439e4bfSJean-Christophe PLAGNIOL-VILLARD * we assume that they are GMII-based, and TBI compatibility is not 19852439e4bfSJean-Christophe PLAGNIOL-VILLARD * needed. If no other speeds are advertised, we assume the link 19862439e4bfSJean-Christophe PLAGNIOL-VILLARD * partner is TBI-based, and we turn on TBI Compatibility. 19872439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 19882439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->tbi_compatibility_en) { 19892439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg 19902439e4bfSJean-Christophe PLAGNIOL-VILLARD (hw, PHY_LP_ABILITY, &lp_capability) < 0) { 19912439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 19922439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 19932439e4bfSJean-Christophe PLAGNIOL-VILLARD } 19942439e4bfSJean-Christophe PLAGNIOL-VILLARD if (lp_capability & (NWAY_LPAR_10T_HD_CAPS | 19952439e4bfSJean-Christophe PLAGNIOL-VILLARD NWAY_LPAR_10T_FD_CAPS | 19962439e4bfSJean-Christophe PLAGNIOL-VILLARD NWAY_LPAR_100TX_HD_CAPS | 19972439e4bfSJean-Christophe PLAGNIOL-VILLARD NWAY_LPAR_100TX_FD_CAPS | 19982439e4bfSJean-Christophe PLAGNIOL-VILLARD NWAY_LPAR_100T4_CAPS)) { 19992439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If our link partner advertises anything in addition to 20002439e4bfSJean-Christophe PLAGNIOL-VILLARD * gigabit, we do not need to enable TBI compatibility. 20012439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 20022439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->tbi_compatibility_on) { 20032439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If we previously were in the mode, turn it off. */ 20042439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl = E1000_READ_REG(hw, RCTL); 20052439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl &= ~E1000_RCTL_SBP; 20062439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, rctl); 20072439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->tbi_compatibility_on = FALSE; 20082439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20092439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 20102439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If TBI compatibility is was previously off, turn it on. For 20112439e4bfSJean-Christophe PLAGNIOL-VILLARD * compatibility with a TBI link partner, we will store bad 20122439e4bfSJean-Christophe PLAGNIOL-VILLARD * packets. Some frames have an additional byte on the end and 20132439e4bfSJean-Christophe PLAGNIOL-VILLARD * will look like CRC errors to to the hardware. 20142439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 20152439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!hw->tbi_compatibility_on) { 20162439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->tbi_compatibility_on = TRUE; 20172439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl = E1000_READ_REG(hw, RCTL); 20182439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl |= E1000_RCTL_SBP; 20192439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, rctl); 20202439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20212439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20222439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20232439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20242439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If we don't have link (auto-negotiation failed or link partner cannot 20252439e4bfSJean-Christophe PLAGNIOL-VILLARD * auto-negotiate), the cable is plugged in (we have signal), and our 20262439e4bfSJean-Christophe PLAGNIOL-VILLARD * link partner is not trying to auto-negotiate with us (we are receiving 20272439e4bfSJean-Christophe PLAGNIOL-VILLARD * idles or data), we need to force link up. We also need to give 20282439e4bfSJean-Christophe PLAGNIOL-VILLARD * auto-negotiation time to complete, in case the cable was just plugged 20292439e4bfSJean-Christophe PLAGNIOL-VILLARD * in. The autoneg_failed flag does this. 20302439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 20312439e4bfSJean-Christophe PLAGNIOL-VILLARD else if ((hw->media_type == e1000_media_type_fiber) && 20322439e4bfSJean-Christophe PLAGNIOL-VILLARD (!(status & E1000_STATUS_LU)) && 20332439e4bfSJean-Christophe PLAGNIOL-VILLARD ((ctrl & E1000_CTRL_SWDPIN1) == signal) && 20342439e4bfSJean-Christophe PLAGNIOL-VILLARD (!(rxcw & E1000_RXCW_C))) { 20352439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->autoneg_failed == 0) { 20362439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->autoneg_failed = 1; 20372439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 20382439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20392439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n"); 20402439e4bfSJean-Christophe PLAGNIOL-VILLARD 20412439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Disable auto-negotiation in the TXCW register */ 20422439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE)); 20432439e4bfSJean-Christophe PLAGNIOL-VILLARD 20442439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Force link-up and also force full-duplex. */ 20452439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 20462439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); 20472439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 20482439e4bfSJean-Christophe PLAGNIOL-VILLARD 20492439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Configure Flow Control after forcing link up. */ 20502439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_config_fc_after_link_up(hw); 20512439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 20522439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Error configuring flow control\n"); 20532439e4bfSJean-Christophe PLAGNIOL-VILLARD return ret_val; 20542439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20552439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20562439e4bfSJean-Christophe PLAGNIOL-VILLARD /* If we are forcing link and we are receiving /C/ ordered sets, re-enable 20572439e4bfSJean-Christophe PLAGNIOL-VILLARD * auto-negotiation in the TXCW register and disable forced link in the 20582439e4bfSJean-Christophe PLAGNIOL-VILLARD * Device Control register in an attempt to auto-negotiate with our link 20592439e4bfSJean-Christophe PLAGNIOL-VILLARD * partner. 20602439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 20612439e4bfSJean-Christophe PLAGNIOL-VILLARD else if ((hw->media_type == e1000_media_type_fiber) && 20622439e4bfSJean-Christophe PLAGNIOL-VILLARD (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { 20632439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT 20642439e4bfSJean-Christophe PLAGNIOL-VILLARD ("RXing /C/, enable AutoNeg and stop forcing link.\r\n"); 20652439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TXCW, hw->txcw); 20662439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); 20672439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20682439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 20692439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20702439e4bfSJean-Christophe PLAGNIOL-VILLARD 20712439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 20722439e4bfSJean-Christophe PLAGNIOL-VILLARD * Detects the current speed and duplex settings of the hardware. 20732439e4bfSJean-Christophe PLAGNIOL-VILLARD * 20742439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 20752439e4bfSJean-Christophe PLAGNIOL-VILLARD * speed - Speed of the connection 20762439e4bfSJean-Christophe PLAGNIOL-VILLARD * duplex - Duplex setting of the connection 20772439e4bfSJean-Christophe PLAGNIOL-VILLARD *****************************************************************************/ 20782439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 20792439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_get_speed_and_duplex(struct e1000_hw *hw, 20802439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t * speed, uint16_t * duplex) 20812439e4bfSJean-Christophe PLAGNIOL-VILLARD { 20822439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t status; 20832439e4bfSJean-Christophe PLAGNIOL-VILLARD 20842439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 20852439e4bfSJean-Christophe PLAGNIOL-VILLARD 20862439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82543) { 20872439e4bfSJean-Christophe PLAGNIOL-VILLARD status = E1000_READ_REG(hw, STATUS); 20882439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & E1000_STATUS_SPEED_1000) { 20892439e4bfSJean-Christophe PLAGNIOL-VILLARD *speed = SPEED_1000; 20902439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("1000 Mbs, "); 20912439e4bfSJean-Christophe PLAGNIOL-VILLARD } else if (status & E1000_STATUS_SPEED_100) { 20922439e4bfSJean-Christophe PLAGNIOL-VILLARD *speed = SPEED_100; 20932439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("100 Mbs, "); 20942439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 20952439e4bfSJean-Christophe PLAGNIOL-VILLARD *speed = SPEED_10; 20962439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("10 Mbs, "); 20972439e4bfSJean-Christophe PLAGNIOL-VILLARD } 20982439e4bfSJean-Christophe PLAGNIOL-VILLARD 20992439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & E1000_STATUS_FD) { 21002439e4bfSJean-Christophe PLAGNIOL-VILLARD *duplex = FULL_DUPLEX; 21012439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Full Duplex\r\n"); 21022439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 21032439e4bfSJean-Christophe PLAGNIOL-VILLARD *duplex = HALF_DUPLEX; 21042439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT(" Half Duplex\r\n"); 21052439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21062439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 21072439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("1000 Mbs, Full Duplex\r\n"); 21082439e4bfSJean-Christophe PLAGNIOL-VILLARD *speed = SPEED_1000; 21092439e4bfSJean-Christophe PLAGNIOL-VILLARD *duplex = FULL_DUPLEX; 21102439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21112439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21122439e4bfSJean-Christophe PLAGNIOL-VILLARD 21132439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 21142439e4bfSJean-Christophe PLAGNIOL-VILLARD * Blocks until autoneg completes or times out (~4.5 seconds) 21152439e4bfSJean-Christophe PLAGNIOL-VILLARD * 21162439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 21172439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 21182439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 21192439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_wait_autoneg(struct e1000_hw *hw) 21202439e4bfSJean-Christophe PLAGNIOL-VILLARD { 21212439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t i; 21222439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t phy_data; 21232439e4bfSJean-Christophe PLAGNIOL-VILLARD 21242439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 21252439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Waiting for Auto-Neg to complete.\n"); 21262439e4bfSJean-Christophe PLAGNIOL-VILLARD 21272439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We will wait for autoneg to complete or 4.5 seconds to expire. */ 21282439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = PHY_AUTO_NEG_TIME; i > 0; i--) { 21292439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the MII Status Register and wait for Auto-Neg 21302439e4bfSJean-Christophe PLAGNIOL-VILLARD * Complete bit to be set. 21312439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 21322439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { 21332439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 21342439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 21352439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21362439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { 21372439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 21382439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 21392439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21402439e4bfSJean-Christophe PLAGNIOL-VILLARD if (phy_data & MII_SR_AUTONEG_COMPLETE) { 21412439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Auto-Neg complete.\n"); 21422439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 21432439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21442439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(100); 21452439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21462439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Auto-Neg timedout.\n"); 21472439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_TIMEOUT; 21482439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21492439e4bfSJean-Christophe PLAGNIOL-VILLARD 21502439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 21512439e4bfSJean-Christophe PLAGNIOL-VILLARD * Raises the Management Data Clock 21522439e4bfSJean-Christophe PLAGNIOL-VILLARD * 21532439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 21542439e4bfSJean-Christophe PLAGNIOL-VILLARD * ctrl - Device control register's current value 21552439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 21562439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 21572439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t * ctrl) 21582439e4bfSJean-Christophe PLAGNIOL-VILLARD { 21592439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Raise the clock input to the Management Data Clock (by setting the MDC 21602439e4bfSJean-Christophe PLAGNIOL-VILLARD * bit), and then delay 2 microseconds. 21612439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 21622439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC)); 21632439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 21642439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(2); 21652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21662439e4bfSJean-Christophe PLAGNIOL-VILLARD 21672439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 21682439e4bfSJean-Christophe PLAGNIOL-VILLARD * Lowers the Management Data Clock 21692439e4bfSJean-Christophe PLAGNIOL-VILLARD * 21702439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 21712439e4bfSJean-Christophe PLAGNIOL-VILLARD * ctrl - Device control register's current value 21722439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 21732439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 21742439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t * ctrl) 21752439e4bfSJean-Christophe PLAGNIOL-VILLARD { 21762439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Lower the clock input to the Management Data Clock (by clearing the MDC 21772439e4bfSJean-Christophe PLAGNIOL-VILLARD * bit), and then delay 2 microseconds. 21782439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 21792439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC)); 21802439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 21812439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(2); 21822439e4bfSJean-Christophe PLAGNIOL-VILLARD } 21832439e4bfSJean-Christophe PLAGNIOL-VILLARD 21842439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 21852439e4bfSJean-Christophe PLAGNIOL-VILLARD * Shifts data bits out to the PHY 21862439e4bfSJean-Christophe PLAGNIOL-VILLARD * 21872439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 21882439e4bfSJean-Christophe PLAGNIOL-VILLARD * data - Data to send out to the PHY 21892439e4bfSJean-Christophe PLAGNIOL-VILLARD * count - Number of bits to shift out 21902439e4bfSJean-Christophe PLAGNIOL-VILLARD * 21912439e4bfSJean-Christophe PLAGNIOL-VILLARD * Bits are shifted out in MSB to LSB order. 21922439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 21932439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 21942439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count) 21952439e4bfSJean-Christophe PLAGNIOL-VILLARD { 21962439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 21972439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t mask; 21982439e4bfSJean-Christophe PLAGNIOL-VILLARD 21992439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We need to shift "count" number of bits out to the PHY. So, the value 22002439e4bfSJean-Christophe PLAGNIOL-VILLARD * in the "data" parameter will be shifted out to the PHY one bit at a 22012439e4bfSJean-Christophe PLAGNIOL-VILLARD * time. In order to do this, "data" must be broken down into bits. 22022439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 22032439e4bfSJean-Christophe PLAGNIOL-VILLARD mask = 0x01; 22042439e4bfSJean-Christophe PLAGNIOL-VILLARD mask <<= (count - 1); 22052439e4bfSJean-Christophe PLAGNIOL-VILLARD 22062439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 22072439e4bfSJean-Christophe PLAGNIOL-VILLARD 22082439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ 22092439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); 22102439e4bfSJean-Christophe PLAGNIOL-VILLARD 22112439e4bfSJean-Christophe PLAGNIOL-VILLARD while (mask) { 22122439e4bfSJean-Christophe PLAGNIOL-VILLARD /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and 22132439e4bfSJean-Christophe PLAGNIOL-VILLARD * then raising and lowering the Management Data Clock. A "0" is 22142439e4bfSJean-Christophe PLAGNIOL-VILLARD * shifted out to the PHY by setting the MDIO bit to "0" and then 22152439e4bfSJean-Christophe PLAGNIOL-VILLARD * raising and lowering the clock. 22162439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 22172439e4bfSJean-Christophe PLAGNIOL-VILLARD if (data & mask) 22182439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl |= E1000_CTRL_MDIO; 22192439e4bfSJean-Christophe PLAGNIOL-VILLARD else 22202439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= ~E1000_CTRL_MDIO; 22212439e4bfSJean-Christophe PLAGNIOL-VILLARD 22222439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 22232439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 22242439e4bfSJean-Christophe PLAGNIOL-VILLARD 22252439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(2); 22262439e4bfSJean-Christophe PLAGNIOL-VILLARD 22272439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_mdi_clk(hw, &ctrl); 22282439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_mdi_clk(hw, &ctrl); 22292439e4bfSJean-Christophe PLAGNIOL-VILLARD 22302439e4bfSJean-Christophe PLAGNIOL-VILLARD mask = mask >> 1; 22312439e4bfSJean-Christophe PLAGNIOL-VILLARD } 22322439e4bfSJean-Christophe PLAGNIOL-VILLARD } 22332439e4bfSJean-Christophe PLAGNIOL-VILLARD 22342439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 22352439e4bfSJean-Christophe PLAGNIOL-VILLARD * Shifts data bits in from the PHY 22362439e4bfSJean-Christophe PLAGNIOL-VILLARD * 22372439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 22382439e4bfSJean-Christophe PLAGNIOL-VILLARD * 22392439e4bfSJean-Christophe PLAGNIOL-VILLARD * Bits are shifted in in MSB to LSB order. 22402439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 22412439e4bfSJean-Christophe PLAGNIOL-VILLARD static uint16_t 22422439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_in_mdi_bits(struct e1000_hw *hw) 22432439e4bfSJean-Christophe PLAGNIOL-VILLARD { 22442439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 22452439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t data = 0; 22462439e4bfSJean-Christophe PLAGNIOL-VILLARD uint8_t i; 22472439e4bfSJean-Christophe PLAGNIOL-VILLARD 22482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* In order to read a register from the PHY, we need to shift in a total 22492439e4bfSJean-Christophe PLAGNIOL-VILLARD * of 18 bits from the PHY. The first two bit (turnaround) times are used 22502439e4bfSJean-Christophe PLAGNIOL-VILLARD * to avoid contention on the MDIO pin when a read operation is performed. 22512439e4bfSJean-Christophe PLAGNIOL-VILLARD * These two bits are ignored by us and thrown away. Bits are "shifted in" 22522439e4bfSJean-Christophe PLAGNIOL-VILLARD * by raising the input to the Management Data Clock (setting the MDC bit), 22532439e4bfSJean-Christophe PLAGNIOL-VILLARD * and then reading the value of the MDIO bit. 22542439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 22552439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 22562439e4bfSJean-Christophe PLAGNIOL-VILLARD 22572439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */ 22582439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= ~E1000_CTRL_MDIO_DIR; 22592439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl &= ~E1000_CTRL_MDIO; 22602439e4bfSJean-Christophe PLAGNIOL-VILLARD 22612439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 22622439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 22632439e4bfSJean-Christophe PLAGNIOL-VILLARD 22642439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Raise and Lower the clock before reading in the data. This accounts for 22652439e4bfSJean-Christophe PLAGNIOL-VILLARD * the turnaround bits. The first clock occurred when we clocked out the 22662439e4bfSJean-Christophe PLAGNIOL-VILLARD * last bit of the Register Address. 22672439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 22682439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_mdi_clk(hw, &ctrl); 22692439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_mdi_clk(hw, &ctrl); 22702439e4bfSJean-Christophe PLAGNIOL-VILLARD 22712439e4bfSJean-Christophe PLAGNIOL-VILLARD for (data = 0, i = 0; i < 16; i++) { 22722439e4bfSJean-Christophe PLAGNIOL-VILLARD data = data << 1; 22732439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_mdi_clk(hw, &ctrl); 22742439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 22752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check to see if we shifted in a "1". */ 22762439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ctrl & E1000_CTRL_MDIO) 22772439e4bfSJean-Christophe PLAGNIOL-VILLARD data |= 1; 22782439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_mdi_clk(hw, &ctrl); 22792439e4bfSJean-Christophe PLAGNIOL-VILLARD } 22802439e4bfSJean-Christophe PLAGNIOL-VILLARD 22812439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_raise_mdi_clk(hw, &ctrl); 22822439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_lower_mdi_clk(hw, &ctrl); 22832439e4bfSJean-Christophe PLAGNIOL-VILLARD 22842439e4bfSJean-Christophe PLAGNIOL-VILLARD return data; 22852439e4bfSJean-Christophe PLAGNIOL-VILLARD } 22862439e4bfSJean-Christophe PLAGNIOL-VILLARD 22872439e4bfSJean-Christophe PLAGNIOL-VILLARD /***************************************************************************** 22882439e4bfSJean-Christophe PLAGNIOL-VILLARD * Reads the value from a PHY register 22892439e4bfSJean-Christophe PLAGNIOL-VILLARD * 22902439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 22912439e4bfSJean-Christophe PLAGNIOL-VILLARD * reg_addr - address of the PHY register to read 22922439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 22932439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 22942439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t * phy_data) 22952439e4bfSJean-Christophe PLAGNIOL-VILLARD { 22962439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t i; 22972439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t mdic = 0; 22982439e4bfSJean-Christophe PLAGNIOL-VILLARD const uint32_t phy_addr = 1; 22992439e4bfSJean-Christophe PLAGNIOL-VILLARD 23002439e4bfSJean-Christophe PLAGNIOL-VILLARD if (reg_addr > MAX_PHY_REG_ADDRESS) { 23012439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Address %d is out of range\n", reg_addr); 23022439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PARAM; 23032439e4bfSJean-Christophe PLAGNIOL-VILLARD } 23042439e4bfSJean-Christophe PLAGNIOL-VILLARD 23052439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82543) { 23062439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set up Op-code, Phy Address, and register address in the MDI 23072439e4bfSJean-Christophe PLAGNIOL-VILLARD * Control register. The MAC will take care of interfacing with the 23082439e4bfSJean-Christophe PLAGNIOL-VILLARD * PHY to retrieve the desired data. 23092439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 23102439e4bfSJean-Christophe PLAGNIOL-VILLARD mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | 23112439e4bfSJean-Christophe PLAGNIOL-VILLARD (phy_addr << E1000_MDIC_PHY_SHIFT) | 23122439e4bfSJean-Christophe PLAGNIOL-VILLARD (E1000_MDIC_OP_READ)); 23132439e4bfSJean-Christophe PLAGNIOL-VILLARD 23142439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, MDIC, mdic); 23152439e4bfSJean-Christophe PLAGNIOL-VILLARD 23162439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Poll the ready bit to see if the MDI read completed */ 23172439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 64; i++) { 23182439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10); 23192439e4bfSJean-Christophe PLAGNIOL-VILLARD mdic = E1000_READ_REG(hw, MDIC); 23202439e4bfSJean-Christophe PLAGNIOL-VILLARD if (mdic & E1000_MDIC_READY) 23212439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 23222439e4bfSJean-Christophe PLAGNIOL-VILLARD } 23232439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(mdic & E1000_MDIC_READY)) { 23242439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("MDI Read did not complete\n"); 23252439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 23262439e4bfSJean-Christophe PLAGNIOL-VILLARD } 23272439e4bfSJean-Christophe PLAGNIOL-VILLARD if (mdic & E1000_MDIC_ERROR) { 23282439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("MDI Error\n"); 23292439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 23302439e4bfSJean-Christophe PLAGNIOL-VILLARD } 23312439e4bfSJean-Christophe PLAGNIOL-VILLARD *phy_data = (uint16_t) mdic; 23322439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 23332439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We must first send a preamble through the MDIO pin to signal the 23342439e4bfSJean-Christophe PLAGNIOL-VILLARD * beginning of an MII instruction. This is done by sending 32 23352439e4bfSJean-Christophe PLAGNIOL-VILLARD * consecutive "1" bits. 23362439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 23372439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); 23382439e4bfSJean-Christophe PLAGNIOL-VILLARD 23392439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Now combine the next few fields that are required for a read 23402439e4bfSJean-Christophe PLAGNIOL-VILLARD * operation. We use this method instead of calling the 23412439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_shift_out_mdi_bits routine five different times. The format of 23422439e4bfSJean-Christophe PLAGNIOL-VILLARD * a MII read instruction consists of a shift out of 14 bits and is 23432439e4bfSJean-Christophe PLAGNIOL-VILLARD * defined as follows: 23442439e4bfSJean-Christophe PLAGNIOL-VILLARD * <Preamble><SOF><Op Code><Phy Addr><Reg Addr> 23452439e4bfSJean-Christophe PLAGNIOL-VILLARD * followed by a shift in of 18 bits. This first two bits shifted in 23462439e4bfSJean-Christophe PLAGNIOL-VILLARD * are TurnAround bits used to avoid contention on the MDIO pin when a 23472439e4bfSJean-Christophe PLAGNIOL-VILLARD * READ operation is performed. These two bits are thrown away 23482439e4bfSJean-Christophe PLAGNIOL-VILLARD * followed by a shift in of 16 bits which contains the desired data. 23492439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 23502439e4bfSJean-Christophe PLAGNIOL-VILLARD mdic = ((reg_addr) | (phy_addr << 5) | 23512439e4bfSJean-Christophe PLAGNIOL-VILLARD (PHY_OP_READ << 10) | (PHY_SOF << 12)); 23522439e4bfSJean-Christophe PLAGNIOL-VILLARD 23532439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_mdi_bits(hw, mdic, 14); 23542439e4bfSJean-Christophe PLAGNIOL-VILLARD 23552439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Now that we've shifted out the read command to the MII, we need to 23562439e4bfSJean-Christophe PLAGNIOL-VILLARD * "shift in" the 16-bit value (18 total bits) of the requested PHY 23572439e4bfSJean-Christophe PLAGNIOL-VILLARD * register address. 23582439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 23592439e4bfSJean-Christophe PLAGNIOL-VILLARD *phy_data = e1000_shift_in_mdi_bits(hw); 23602439e4bfSJean-Christophe PLAGNIOL-VILLARD } 23612439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 23622439e4bfSJean-Christophe PLAGNIOL-VILLARD } 23632439e4bfSJean-Christophe PLAGNIOL-VILLARD 23642439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 23652439e4bfSJean-Christophe PLAGNIOL-VILLARD * Writes a value to a PHY register 23662439e4bfSJean-Christophe PLAGNIOL-VILLARD * 23672439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 23682439e4bfSJean-Christophe PLAGNIOL-VILLARD * reg_addr - address of the PHY register to write 23692439e4bfSJean-Christophe PLAGNIOL-VILLARD * data - data to write to the PHY 23702439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 23712439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 23722439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t phy_data) 23732439e4bfSJean-Christophe PLAGNIOL-VILLARD { 23742439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t i; 23752439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t mdic = 0; 23762439e4bfSJean-Christophe PLAGNIOL-VILLARD const uint32_t phy_addr = 1; 23772439e4bfSJean-Christophe PLAGNIOL-VILLARD 23782439e4bfSJean-Christophe PLAGNIOL-VILLARD if (reg_addr > MAX_PHY_REG_ADDRESS) { 23792439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Address %d is out of range\n", reg_addr); 23802439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PARAM; 23812439e4bfSJean-Christophe PLAGNIOL-VILLARD } 23822439e4bfSJean-Christophe PLAGNIOL-VILLARD 23832439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82543) { 23842439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set up Op-code, Phy Address, register address, and data intended 23852439e4bfSJean-Christophe PLAGNIOL-VILLARD * for the PHY register in the MDI Control register. The MAC will take 23862439e4bfSJean-Christophe PLAGNIOL-VILLARD * care of interfacing with the PHY to send the desired data. 23872439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 23882439e4bfSJean-Christophe PLAGNIOL-VILLARD mdic = (((uint32_t) phy_data) | 23892439e4bfSJean-Christophe PLAGNIOL-VILLARD (reg_addr << E1000_MDIC_REG_SHIFT) | 23902439e4bfSJean-Christophe PLAGNIOL-VILLARD (phy_addr << E1000_MDIC_PHY_SHIFT) | 23912439e4bfSJean-Christophe PLAGNIOL-VILLARD (E1000_MDIC_OP_WRITE)); 23922439e4bfSJean-Christophe PLAGNIOL-VILLARD 23932439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, MDIC, mdic); 23942439e4bfSJean-Christophe PLAGNIOL-VILLARD 23952439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Poll the ready bit to see if the MDI read completed */ 23962439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 64; i++) { 23972439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10); 23982439e4bfSJean-Christophe PLAGNIOL-VILLARD mdic = E1000_READ_REG(hw, MDIC); 23992439e4bfSJean-Christophe PLAGNIOL-VILLARD if (mdic & E1000_MDIC_READY) 24002439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 24012439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24022439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(mdic & E1000_MDIC_READY)) { 24032439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("MDI Write did not complete\n"); 24042439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 24052439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24062439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 24072439e4bfSJean-Christophe PLAGNIOL-VILLARD /* We'll need to use the SW defined pins to shift the write command 24082439e4bfSJean-Christophe PLAGNIOL-VILLARD * out to the PHY. We first send a preamble to the PHY to signal the 24092439e4bfSJean-Christophe PLAGNIOL-VILLARD * beginning of the MII instruction. This is done by sending 32 24102439e4bfSJean-Christophe PLAGNIOL-VILLARD * consecutive "1" bits. 24112439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 24122439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); 24132439e4bfSJean-Christophe PLAGNIOL-VILLARD 24142439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Now combine the remaining required fields that will indicate a 24152439e4bfSJean-Christophe PLAGNIOL-VILLARD * write operation. We use this method instead of calling the 24162439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_shift_out_mdi_bits routine for each field in the command. The 24172439e4bfSJean-Christophe PLAGNIOL-VILLARD * format of a MII write instruction is as follows: 24182439e4bfSJean-Christophe PLAGNIOL-VILLARD * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>. 24192439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 24202439e4bfSJean-Christophe PLAGNIOL-VILLARD mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) | 24212439e4bfSJean-Christophe PLAGNIOL-VILLARD (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); 24222439e4bfSJean-Christophe PLAGNIOL-VILLARD mdic <<= 16; 24232439e4bfSJean-Christophe PLAGNIOL-VILLARD mdic |= (uint32_t) phy_data; 24242439e4bfSJean-Christophe PLAGNIOL-VILLARD 24252439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_shift_out_mdi_bits(hw, mdic, 32); 24262439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24272439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 24282439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24292439e4bfSJean-Christophe PLAGNIOL-VILLARD 24302439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 24312439e4bfSJean-Christophe PLAGNIOL-VILLARD * Returns the PHY to the power-on reset state 24322439e4bfSJean-Christophe PLAGNIOL-VILLARD * 24332439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 24342439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 24352439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 24362439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_phy_hw_reset(struct e1000_hw *hw) 24372439e4bfSJean-Christophe PLAGNIOL-VILLARD { 24382439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl; 24392439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t ctrl_ext; 24402439e4bfSJean-Christophe PLAGNIOL-VILLARD 24412439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 24422439e4bfSJean-Christophe PLAGNIOL-VILLARD 24432439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Resetting Phy...\n"); 24442439e4bfSJean-Christophe PLAGNIOL-VILLARD 24452439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type > e1000_82543) { 24462439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the device control register and assert the E1000_CTRL_PHY_RST 24472439e4bfSJean-Christophe PLAGNIOL-VILLARD * bit. Then, take it out of reset. 24482439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 24492439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl = E1000_READ_REG(hw, CTRL); 24502439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST); 24512439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 24522439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(10); 24532439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, ctrl); 24542439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 24552439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 24562439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the Extended Device Control Register, assert the PHY_RESET_DIR 24572439e4bfSJean-Christophe PLAGNIOL-VILLARD * bit to put the PHY into reset. Then, take it out of reset. 24582439e4bfSJean-Christophe PLAGNIOL-VILLARD */ 24592439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); 24602439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; 24612439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; 24622439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); 24632439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 24642439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(10); 24652439e4bfSJean-Christophe PLAGNIOL-VILLARD ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; 24662439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); 24672439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_FLUSH(hw); 24682439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24692439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(150); 24702439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24712439e4bfSJean-Christophe PLAGNIOL-VILLARD 24722439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 24732439e4bfSJean-Christophe PLAGNIOL-VILLARD * Resets the PHY 24742439e4bfSJean-Christophe PLAGNIOL-VILLARD * 24752439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 24762439e4bfSJean-Christophe PLAGNIOL-VILLARD * 24772439e4bfSJean-Christophe PLAGNIOL-VILLARD * Sets bit 15 of the MII Control regiser 24782439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 24792439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 24802439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_phy_reset(struct e1000_hw *hw) 24812439e4bfSJean-Christophe PLAGNIOL-VILLARD { 24822439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t phy_data; 24832439e4bfSJean-Christophe PLAGNIOL-VILLARD 24842439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 24852439e4bfSJean-Christophe PLAGNIOL-VILLARD 24862439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) { 24872439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 24882439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 24892439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24902439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_data |= MII_CR_RESET; 24912439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) { 24922439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Write Error\n"); 24932439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 24942439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24952439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1); 24962439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 24972439e4bfSJean-Christophe PLAGNIOL-VILLARD } 24982439e4bfSJean-Christophe PLAGNIOL-VILLARD 24991aeed8d7SWolfgang Denk static int e1000_set_phy_type (struct e1000_hw *hw) 2500ac3315c2SAndre Schwarz { 2501ac3315c2SAndre Schwarz DEBUGFUNC (); 2502ac3315c2SAndre Schwarz 2503ac3315c2SAndre Schwarz if (hw->mac_type == e1000_undefined) 2504ac3315c2SAndre Schwarz return -E1000_ERR_PHY_TYPE; 2505ac3315c2SAndre Schwarz 2506ac3315c2SAndre Schwarz switch (hw->phy_id) { 2507ac3315c2SAndre Schwarz case M88E1000_E_PHY_ID: 2508ac3315c2SAndre Schwarz case M88E1000_I_PHY_ID: 2509ac3315c2SAndre Schwarz case M88E1011_I_PHY_ID: 2510ac3315c2SAndre Schwarz hw->phy_type = e1000_phy_m88; 2511ac3315c2SAndre Schwarz break; 2512ac3315c2SAndre Schwarz case IGP01E1000_I_PHY_ID: 2513ac3315c2SAndre Schwarz if (hw->mac_type == e1000_82541 || 2514ac3315c2SAndre Schwarz hw->mac_type == e1000_82541_rev_2) { 2515ac3315c2SAndre Schwarz hw->phy_type = e1000_phy_igp; 2516ac3315c2SAndre Schwarz break; 2517ac3315c2SAndre Schwarz } 2518ac3315c2SAndre Schwarz /* Fall Through */ 2519ac3315c2SAndre Schwarz default: 2520ac3315c2SAndre Schwarz /* Should never have loaded on this device */ 2521ac3315c2SAndre Schwarz hw->phy_type = e1000_phy_undefined; 2522ac3315c2SAndre Schwarz return -E1000_ERR_PHY_TYPE; 2523ac3315c2SAndre Schwarz } 2524ac3315c2SAndre Schwarz 2525ac3315c2SAndre Schwarz return E1000_SUCCESS; 2526ac3315c2SAndre Schwarz } 2527ac3315c2SAndre Schwarz 25282439e4bfSJean-Christophe PLAGNIOL-VILLARD /****************************************************************************** 25292439e4bfSJean-Christophe PLAGNIOL-VILLARD * Probes the expected PHY address for known PHY IDs 25302439e4bfSJean-Christophe PLAGNIOL-VILLARD * 25312439e4bfSJean-Christophe PLAGNIOL-VILLARD * hw - Struct containing variables accessed by shared code 25322439e4bfSJean-Christophe PLAGNIOL-VILLARD ******************************************************************************/ 25332439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 25342439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_detect_gig_phy(struct e1000_hw *hw) 25352439e4bfSJean-Christophe PLAGNIOL-VILLARD { 2536ac3315c2SAndre Schwarz int32_t phy_init_status; 25372439e4bfSJean-Christophe PLAGNIOL-VILLARD uint16_t phy_id_high, phy_id_low; 25382439e4bfSJean-Christophe PLAGNIOL-VILLARD int match = FALSE; 25392439e4bfSJean-Christophe PLAGNIOL-VILLARD 25402439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGFUNC(); 25412439e4bfSJean-Christophe PLAGNIOL-VILLARD 25422439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read the PHY ID Registers to identify which PHY is onboard. */ 25432439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high) < 0) { 25442439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 25452439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 25462439e4bfSJean-Christophe PLAGNIOL-VILLARD } 25472439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->phy_id = (uint32_t) (phy_id_high << 16); 25482439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(2); 25492439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { 25502439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY Read Error\n"); 25512439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 25522439e4bfSJean-Christophe PLAGNIOL-VILLARD } 25532439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); 25542439e4bfSJean-Christophe PLAGNIOL-VILLARD 25552439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (hw->mac_type) { 25562439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_82543: 25572439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->phy_id == M88E1000_E_PHY_ID) 25582439e4bfSJean-Christophe PLAGNIOL-VILLARD match = TRUE; 25592439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 25602439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_82544: 25612439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->phy_id == M88E1000_I_PHY_ID) 25622439e4bfSJean-Christophe PLAGNIOL-VILLARD match = TRUE; 25632439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 25642439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_82540: 25652439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_82545: 25662439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_82546: 25672439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->phy_id == M88E1011_I_PHY_ID) 25682439e4bfSJean-Christophe PLAGNIOL-VILLARD match = TRUE; 25692439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 2570ac3315c2SAndre Schwarz case e1000_82541_rev_2: 2571ac3315c2SAndre Schwarz if(hw->phy_id == IGP01E1000_I_PHY_ID) 2572ac3315c2SAndre Schwarz match = TRUE; 2573ac3315c2SAndre Schwarz 2574ac3315c2SAndre Schwarz break; 25752439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 25762439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Invalid MAC type %d\n", hw->mac_type); 25772439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_CONFIG; 25782439e4bfSJean-Christophe PLAGNIOL-VILLARD } 2579ac3315c2SAndre Schwarz 2580ac3315c2SAndre Schwarz phy_init_status = e1000_set_phy_type(hw); 2581ac3315c2SAndre Schwarz 2582ac3315c2SAndre Schwarz if ((match) && (phy_init_status == E1000_SUCCESS)) { 25832439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("PHY ID 0x%X detected\n", hw->phy_id); 25842439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 25852439e4bfSJean-Christophe PLAGNIOL-VILLARD } 25862439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("Invalid PHY ID 0x%X\n", hw->phy_id); 25872439e4bfSJean-Christophe PLAGNIOL-VILLARD return -E1000_ERR_PHY; 25882439e4bfSJean-Christophe PLAGNIOL-VILLARD } 25892439e4bfSJean-Christophe PLAGNIOL-VILLARD 25902439e4bfSJean-Christophe PLAGNIOL-VILLARD /** 25912439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_sw_init - Initialize general software structures (struct e1000_adapter) 25922439e4bfSJean-Christophe PLAGNIOL-VILLARD * 25932439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_sw_init initializes the Adapter private data structure. 25942439e4bfSJean-Christophe PLAGNIOL-VILLARD * Fields are initialized based on PCI device information and 25952439e4bfSJean-Christophe PLAGNIOL-VILLARD * OS network device settings (MTU size). 25962439e4bfSJean-Christophe PLAGNIOL-VILLARD **/ 25972439e4bfSJean-Christophe PLAGNIOL-VILLARD 25982439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 25992439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_sw_init(struct eth_device *nic, int cardnum) 26002439e4bfSJean-Christophe PLAGNIOL-VILLARD { 26012439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = (typeof(hw)) nic->priv; 26022439e4bfSJean-Christophe PLAGNIOL-VILLARD int result; 26032439e4bfSJean-Christophe PLAGNIOL-VILLARD 26042439e4bfSJean-Christophe PLAGNIOL-VILLARD /* PCI config space info */ 26052439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_word(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id); 26062439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_word(hw->pdev, PCI_DEVICE_ID, &hw->device_id); 26072439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID, 26082439e4bfSJean-Christophe PLAGNIOL-VILLARD &hw->subsystem_vendor_id); 26092439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id); 26102439e4bfSJean-Christophe PLAGNIOL-VILLARD 26112439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_byte(hw->pdev, PCI_REVISION_ID, &hw->revision_id); 26122439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_word(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word); 26132439e4bfSJean-Christophe PLAGNIOL-VILLARD 26142439e4bfSJean-Christophe PLAGNIOL-VILLARD /* identify the MAC */ 26152439e4bfSJean-Christophe PLAGNIOL-VILLARD result = e1000_set_mac_type(hw); 26162439e4bfSJean-Christophe PLAGNIOL-VILLARD if (result) { 26172439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_ERR("Unknown MAC Type\n"); 26182439e4bfSJean-Christophe PLAGNIOL-VILLARD return result; 26192439e4bfSJean-Christophe PLAGNIOL-VILLARD } 26202439e4bfSJean-Christophe PLAGNIOL-VILLARD 26212439e4bfSJean-Christophe PLAGNIOL-VILLARD /* lan a vs. lan b settings */ 26222439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type == e1000_82546) 26232439e4bfSJean-Christophe PLAGNIOL-VILLARD /*this also works w/ multiple 82546 cards */ 26242439e4bfSJean-Christophe PLAGNIOL-VILLARD /*but not if they're intermingled /w other e1000s */ 26252439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->lan_loc = (cardnum % 2) ? e1000_lan_b : e1000_lan_a; 26262439e4bfSJean-Christophe PLAGNIOL-VILLARD else 26272439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->lan_loc = e1000_lan_a; 26282439e4bfSJean-Christophe PLAGNIOL-VILLARD 26292439e4bfSJean-Christophe PLAGNIOL-VILLARD /* flow control settings */ 26302439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc_high_water = E1000_FC_HIGH_THRESH; 26312439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc_low_water = E1000_FC_LOW_THRESH; 26322439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc_pause_time = E1000_FC_PAUSE_TIME; 26332439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc_send_xon = 1; 26342439e4bfSJean-Christophe PLAGNIOL-VILLARD 26352439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Media type - copper or fiber */ 26362439e4bfSJean-Christophe PLAGNIOL-VILLARD 26372439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82543) { 26382439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t status = E1000_READ_REG(hw, STATUS); 26392439e4bfSJean-Christophe PLAGNIOL-VILLARD 26402439e4bfSJean-Christophe PLAGNIOL-VILLARD if (status & E1000_STATUS_TBIMODE) { 26412439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("fiber interface\n"); 26422439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->media_type = e1000_media_type_fiber; 26432439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 26442439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("copper interface\n"); 26452439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->media_type = e1000_media_type_copper; 26462439e4bfSJean-Christophe PLAGNIOL-VILLARD } 26472439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 26482439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->media_type = e1000_media_type_fiber; 26492439e4bfSJean-Christophe PLAGNIOL-VILLARD } 26502439e4bfSJean-Christophe PLAGNIOL-VILLARD 26512439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type < e1000_82543) 26522439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->report_tx_early = 0; 26532439e4bfSJean-Christophe PLAGNIOL-VILLARD else 26542439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->report_tx_early = 1; 26552439e4bfSJean-Christophe PLAGNIOL-VILLARD 26562439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->tbi_compatibility_en = TRUE; 26572439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 26582439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->wait_autoneg_complete = FALSE; 26592439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->adaptive_ifs = TRUE; 26602439e4bfSJean-Christophe PLAGNIOL-VILLARD 26612439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Copper options */ 26622439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->media_type == e1000_media_type_copper) { 26632439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mdix = AUTO_ALL_MODES; 26642439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->disable_polarity_correction = FALSE; 26652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 26662439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 26672439e4bfSJean-Christophe PLAGNIOL-VILLARD return E1000_SUCCESS; 26682439e4bfSJean-Christophe PLAGNIOL-VILLARD } 26692439e4bfSJean-Christophe PLAGNIOL-VILLARD 26702439e4bfSJean-Christophe PLAGNIOL-VILLARD void 26712439e4bfSJean-Christophe PLAGNIOL-VILLARD fill_rx(struct e1000_hw *hw) 26722439e4bfSJean-Christophe PLAGNIOL-VILLARD { 26732439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_rx_desc *rd; 26742439e4bfSJean-Christophe PLAGNIOL-VILLARD 26752439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_last = rx_tail; 26762439e4bfSJean-Christophe PLAGNIOL-VILLARD rd = rx_base + rx_tail; 26772439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_tail = (rx_tail + 1) % 8; 26782439e4bfSJean-Christophe PLAGNIOL-VILLARD memset(rd, 0, 16); 26792439e4bfSJean-Christophe PLAGNIOL-VILLARD rd->buffer_addr = cpu_to_le64((u32) & packet); 26802439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDT, rx_tail); 26812439e4bfSJean-Christophe PLAGNIOL-VILLARD } 26822439e4bfSJean-Christophe PLAGNIOL-VILLARD 26832439e4bfSJean-Christophe PLAGNIOL-VILLARD /** 26842439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_configure_tx - Configure 8254x Transmit Unit after Reset 26852439e4bfSJean-Christophe PLAGNIOL-VILLARD * @adapter: board private structure 26862439e4bfSJean-Christophe PLAGNIOL-VILLARD * 26872439e4bfSJean-Christophe PLAGNIOL-VILLARD * Configure the Tx unit of the MAC after a reset. 26882439e4bfSJean-Christophe PLAGNIOL-VILLARD **/ 26892439e4bfSJean-Christophe PLAGNIOL-VILLARD 26902439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 26912439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_configure_tx(struct e1000_hw *hw) 26922439e4bfSJean-Christophe PLAGNIOL-VILLARD { 26932439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long ptr; 26942439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long tctl; 26952439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long tipg; 26962439e4bfSJean-Christophe PLAGNIOL-VILLARD 26972439e4bfSJean-Christophe PLAGNIOL-VILLARD ptr = (u32) tx_pool; 26982439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ptr & 0xf) 26992439e4bfSJean-Christophe PLAGNIOL-VILLARD ptr = (ptr + 0x10) & (~0xf); 27002439e4bfSJean-Christophe PLAGNIOL-VILLARD 27012439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_base = (typeof(tx_base)) ptr; 27022439e4bfSJean-Christophe PLAGNIOL-VILLARD 27032439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TDBAL, (u32) tx_base); 27042439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TDBAH, 0); 27052439e4bfSJean-Christophe PLAGNIOL-VILLARD 27062439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TDLEN, 128); 27072439e4bfSJean-Christophe PLAGNIOL-VILLARD 27082439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Setup the HW Tx Head and Tail descriptor pointers */ 27092439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TDH, 0); 27102439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TDT, 0); 27112439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_tail = 0; 27122439e4bfSJean-Christophe PLAGNIOL-VILLARD 27132439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the default values for the Tx Inter Packet Gap timer */ 27142439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (hw->mac_type) { 27152439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_82542_rev2_0: 27162439e4bfSJean-Christophe PLAGNIOL-VILLARD case e1000_82542_rev2_1: 27172439e4bfSJean-Christophe PLAGNIOL-VILLARD tipg = DEFAULT_82542_TIPG_IPGT; 27182439e4bfSJean-Christophe PLAGNIOL-VILLARD tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 27192439e4bfSJean-Christophe PLAGNIOL-VILLARD tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 27202439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 27212439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 27222439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->media_type == e1000_media_type_fiber) 27232439e4bfSJean-Christophe PLAGNIOL-VILLARD tipg = DEFAULT_82543_TIPG_IPGT_FIBER; 27242439e4bfSJean-Christophe PLAGNIOL-VILLARD else 27252439e4bfSJean-Christophe PLAGNIOL-VILLARD tipg = DEFAULT_82543_TIPG_IPGT_COPPER; 27262439e4bfSJean-Christophe PLAGNIOL-VILLARD tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT; 27272439e4bfSJean-Christophe PLAGNIOL-VILLARD tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; 27282439e4bfSJean-Christophe PLAGNIOL-VILLARD } 27292439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TIPG, tipg); 27302439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 27312439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the Tx Interrupt Delay register */ 27322439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay); 27332439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82540) 27342439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay); 27352439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 27362439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Program the Transmit Control Register */ 27372439e4bfSJean-Christophe PLAGNIOL-VILLARD tctl = E1000_READ_REG(hw, TCTL); 27382439e4bfSJean-Christophe PLAGNIOL-VILLARD tctl &= ~E1000_TCTL_CT; 27392439e4bfSJean-Christophe PLAGNIOL-VILLARD tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | 27402439e4bfSJean-Christophe PLAGNIOL-VILLARD (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); 27412439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TCTL, tctl); 27422439e4bfSJean-Christophe PLAGNIOL-VILLARD 27432439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_config_collision_dist(hw); 27442439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 27452439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Setup Transmit Descriptor Settings for this adapter */ 27462439e4bfSJean-Christophe PLAGNIOL-VILLARD adapter->txd_cmd = E1000_TXD_CMD_IFCS | E1000_TXD_CMD_IDE; 27472439e4bfSJean-Christophe PLAGNIOL-VILLARD 27482439e4bfSJean-Christophe PLAGNIOL-VILLARD if (adapter->hw.report_tx_early == 1) 27492439e4bfSJean-Christophe PLAGNIOL-VILLARD adapter->txd_cmd |= E1000_TXD_CMD_RS; 27502439e4bfSJean-Christophe PLAGNIOL-VILLARD else 27512439e4bfSJean-Christophe PLAGNIOL-VILLARD adapter->txd_cmd |= E1000_TXD_CMD_RPS; 27522439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 27532439e4bfSJean-Christophe PLAGNIOL-VILLARD } 27542439e4bfSJean-Christophe PLAGNIOL-VILLARD 27552439e4bfSJean-Christophe PLAGNIOL-VILLARD /** 27562439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_setup_rctl - configure the receive control register 27572439e4bfSJean-Christophe PLAGNIOL-VILLARD * @adapter: Board private structure 27582439e4bfSJean-Christophe PLAGNIOL-VILLARD **/ 27592439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 27602439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_rctl(struct e1000_hw *hw) 27612439e4bfSJean-Christophe PLAGNIOL-VILLARD { 27622439e4bfSJean-Christophe PLAGNIOL-VILLARD uint32_t rctl; 27632439e4bfSJean-Christophe PLAGNIOL-VILLARD 27642439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl = E1000_READ_REG(hw, RCTL); 27652439e4bfSJean-Christophe PLAGNIOL-VILLARD 27662439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl &= ~(3 << E1000_RCTL_MO_SHIFT); 27672439e4bfSJean-Christophe PLAGNIOL-VILLARD 27682439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF; /* | 27692439e4bfSJean-Christophe PLAGNIOL-VILLARD (hw.mc_filter_type << E1000_RCTL_MO_SHIFT); */ 27702439e4bfSJean-Christophe PLAGNIOL-VILLARD 27712439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->tbi_compatibility_on == 1) 27722439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl |= E1000_RCTL_SBP; 27732439e4bfSJean-Christophe PLAGNIOL-VILLARD else 27742439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl &= ~E1000_RCTL_SBP; 27752439e4bfSJean-Christophe PLAGNIOL-VILLARD 27762439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl &= ~(E1000_RCTL_SZ_4096); 27772439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 27782439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (adapter->rx_buffer_len) { 27792439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_RXBUFFER_2048: 27802439e4bfSJean-Christophe PLAGNIOL-VILLARD default: 27812439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 27822439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl |= E1000_RCTL_SZ_2048; 27832439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE); 27842439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 27852439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 27862439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_RXBUFFER_4096: 27872439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE; 27882439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 27892439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_RXBUFFER_8192: 27902439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE; 27912439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 27922439e4bfSJean-Christophe PLAGNIOL-VILLARD case E1000_RXBUFFER_16384: 27932439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE; 27942439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 27952439e4bfSJean-Christophe PLAGNIOL-VILLARD } 27962439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 27972439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, rctl); 27982439e4bfSJean-Christophe PLAGNIOL-VILLARD } 27992439e4bfSJean-Christophe PLAGNIOL-VILLARD 28002439e4bfSJean-Christophe PLAGNIOL-VILLARD /** 28012439e4bfSJean-Christophe PLAGNIOL-VILLARD * e1000_configure_rx - Configure 8254x Receive Unit after Reset 28022439e4bfSJean-Christophe PLAGNIOL-VILLARD * @adapter: board private structure 28032439e4bfSJean-Christophe PLAGNIOL-VILLARD * 28042439e4bfSJean-Christophe PLAGNIOL-VILLARD * Configure the Rx unit of the MAC after a reset. 28052439e4bfSJean-Christophe PLAGNIOL-VILLARD **/ 28062439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 28072439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_configure_rx(struct e1000_hw *hw) 28082439e4bfSJean-Christophe PLAGNIOL-VILLARD { 28092439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long ptr; 28102439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long rctl; 28112439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 28122439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned long rxcsum; 28132439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 28142439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_tail = 0; 28152439e4bfSJean-Christophe PLAGNIOL-VILLARD /* make sure receives are disabled while setting up the descriptors */ 28162439e4bfSJean-Christophe PLAGNIOL-VILLARD rctl = E1000_READ_REG(hw, RCTL); 28172439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); 28182439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 28192439e4bfSJean-Christophe PLAGNIOL-VILLARD /* set the Receive Delay Timer Register */ 28202439e4bfSJean-Christophe PLAGNIOL-VILLARD 28212439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay); 28222439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 28232439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82540) { 28242439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 28252439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); 28262439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 28272439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set the interrupt throttling rate. Value is calculated 28282439e4bfSJean-Christophe PLAGNIOL-VILLARD * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */ 28292439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MAX_INTS_PER_SEC 8000 28302439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) 28312439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, ITR, DEFAULT_ITR); 28322439e4bfSJean-Christophe PLAGNIOL-VILLARD } 28332439e4bfSJean-Christophe PLAGNIOL-VILLARD 28342439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Setup the Base and Length of the Rx Descriptor Ring */ 28352439e4bfSJean-Christophe PLAGNIOL-VILLARD ptr = (u32) rx_pool; 28362439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ptr & 0xf) 28372439e4bfSJean-Christophe PLAGNIOL-VILLARD ptr = (ptr + 0x10) & (~0xf); 28382439e4bfSJean-Christophe PLAGNIOL-VILLARD rx_base = (typeof(rx_base)) ptr; 28392439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDBAL, (u32) rx_base); 28402439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDBAH, 0); 28412439e4bfSJean-Christophe PLAGNIOL-VILLARD 28422439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDLEN, 128); 28432439e4bfSJean-Christophe PLAGNIOL-VILLARD 28442439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Setup the HW Rx Head and Tail Descriptor Pointers */ 28452439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDH, 0); 28462439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDT, 0); 28472439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 28482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enable 82543 Receive Checksum Offload for TCP and UDP */ 28492439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((adapter->hw.mac_type >= e1000_82543) && (adapter->rx_csum == TRUE)) { 28502439e4bfSJean-Christophe PLAGNIOL-VILLARD rxcsum = E1000_READ_REG(hw, RXCSUM); 28512439e4bfSJean-Christophe PLAGNIOL-VILLARD rxcsum |= E1000_RXCSUM_TUOFL; 28522439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RXCSUM, rxcsum); 28532439e4bfSJean-Christophe PLAGNIOL-VILLARD } 28542439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 28552439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enable Receives */ 28562439e4bfSJean-Christophe PLAGNIOL-VILLARD 28572439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, rctl); 28582439e4bfSJean-Christophe PLAGNIOL-VILLARD fill_rx(hw); 28592439e4bfSJean-Christophe PLAGNIOL-VILLARD } 28602439e4bfSJean-Christophe PLAGNIOL-VILLARD 28612439e4bfSJean-Christophe PLAGNIOL-VILLARD /************************************************************************** 28622439e4bfSJean-Christophe PLAGNIOL-VILLARD POLL - Wait for a frame 28632439e4bfSJean-Christophe PLAGNIOL-VILLARD ***************************************************************************/ 28642439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 28652439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_poll(struct eth_device *nic) 28662439e4bfSJean-Christophe PLAGNIOL-VILLARD { 28672439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 28682439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_rx_desc *rd; 28692439e4bfSJean-Christophe PLAGNIOL-VILLARD /* return true if there's an ethernet packet ready to read */ 28702439e4bfSJean-Christophe PLAGNIOL-VILLARD rd = rx_base + rx_last; 28712439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(le32_to_cpu(rd->status)) & E1000_RXD_STAT_DD) 28722439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 28732439e4bfSJean-Christophe PLAGNIOL-VILLARD /*DEBUGOUT("recv: packet len=%d \n", rd->length); */ 28742439e4bfSJean-Christophe PLAGNIOL-VILLARD NetReceive((uchar *)packet, le32_to_cpu(rd->length)); 28752439e4bfSJean-Christophe PLAGNIOL-VILLARD fill_rx(hw); 28762439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 28772439e4bfSJean-Christophe PLAGNIOL-VILLARD } 28782439e4bfSJean-Christophe PLAGNIOL-VILLARD 28792439e4bfSJean-Christophe PLAGNIOL-VILLARD /************************************************************************** 28802439e4bfSJean-Christophe PLAGNIOL-VILLARD TRANSMIT - Transmit a frame 28812439e4bfSJean-Christophe PLAGNIOL-VILLARD ***************************************************************************/ 28822439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 28832439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_transmit(struct eth_device *nic, volatile void *packet, int length) 28842439e4bfSJean-Christophe PLAGNIOL-VILLARD { 28852439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 28862439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_tx_desc *txp; 28872439e4bfSJean-Christophe PLAGNIOL-VILLARD int i = 0; 28882439e4bfSJean-Christophe PLAGNIOL-VILLARD 28892439e4bfSJean-Christophe PLAGNIOL-VILLARD txp = tx_base + tx_tail; 28902439e4bfSJean-Christophe PLAGNIOL-VILLARD tx_tail = (tx_tail + 1) % 8; 28912439e4bfSJean-Christophe PLAGNIOL-VILLARD 28922439e4bfSJean-Christophe PLAGNIOL-VILLARD txp->buffer_addr = cpu_to_le64(virt_to_bus(packet)); 28932439e4bfSJean-Christophe PLAGNIOL-VILLARD txp->lower.data = cpu_to_le32(E1000_TXD_CMD_RPS | E1000_TXD_CMD_EOP | 28942439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_TXD_CMD_IFCS | length); 28952439e4bfSJean-Christophe PLAGNIOL-VILLARD txp->upper.data = 0; 28962439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TDT, tx_tail); 28972439e4bfSJean-Christophe PLAGNIOL-VILLARD 28982439e4bfSJean-Christophe PLAGNIOL-VILLARD while (!(le32_to_cpu(txp->upper.data) & E1000_TXD_STAT_DD)) { 28992439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i++ > TOUT_LOOP) { 29002439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("e1000: tx timeout\n"); 29012439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 29022439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29032439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(10); /* give the nic a chance to write to the register */ 29042439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29052439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 29062439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29072439e4bfSJean-Christophe PLAGNIOL-VILLARD 29082439e4bfSJean-Christophe PLAGNIOL-VILLARD /*reset function*/ 29092439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline int 29102439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_reset(struct eth_device *nic) 29112439e4bfSJean-Christophe PLAGNIOL-VILLARD { 29122439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 29132439e4bfSJean-Christophe PLAGNIOL-VILLARD 29142439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_reset_hw(hw); 29152439e4bfSJean-Christophe PLAGNIOL-VILLARD if (hw->mac_type >= e1000_82544) { 29162439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, WUC, 0); 29172439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29182439e4bfSJean-Christophe PLAGNIOL-VILLARD return e1000_init_hw(nic); 29192439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29202439e4bfSJean-Christophe PLAGNIOL-VILLARD 29212439e4bfSJean-Christophe PLAGNIOL-VILLARD /************************************************************************** 29222439e4bfSJean-Christophe PLAGNIOL-VILLARD DISABLE - Turn off ethernet interface 29232439e4bfSJean-Christophe PLAGNIOL-VILLARD ***************************************************************************/ 29242439e4bfSJean-Christophe PLAGNIOL-VILLARD static void 29252439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_disable(struct eth_device *nic) 29262439e4bfSJean-Christophe PLAGNIOL-VILLARD { 29272439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 29282439e4bfSJean-Christophe PLAGNIOL-VILLARD 29292439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Turn off the ethernet interface */ 29302439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RCTL, 0); 29312439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TCTL, 0); 29322439e4bfSJean-Christophe PLAGNIOL-VILLARD 29332439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear the transmit ring */ 29342439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TDH, 0); 29352439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, TDT, 0); 29362439e4bfSJean-Christophe PLAGNIOL-VILLARD 29372439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Clear the receive ring */ 29382439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDH, 0); 29392439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, RDT, 0); 29402439e4bfSJean-Christophe PLAGNIOL-VILLARD 29412439e4bfSJean-Christophe PLAGNIOL-VILLARD /* put the card in its initial state */ 29422439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 29432439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, CTRL, E1000_CTRL_RST); 29442439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 29452439e4bfSJean-Christophe PLAGNIOL-VILLARD mdelay(10); 29462439e4bfSJean-Christophe PLAGNIOL-VILLARD 29472439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29482439e4bfSJean-Christophe PLAGNIOL-VILLARD 29492439e4bfSJean-Christophe PLAGNIOL-VILLARD /************************************************************************** 29502439e4bfSJean-Christophe PLAGNIOL-VILLARD INIT - set up ethernet interface(s) 29512439e4bfSJean-Christophe PLAGNIOL-VILLARD ***************************************************************************/ 29522439e4bfSJean-Christophe PLAGNIOL-VILLARD static int 29532439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_init(struct eth_device *nic, bd_t * bis) 29542439e4bfSJean-Christophe PLAGNIOL-VILLARD { 29552439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = nic->priv; 29562439e4bfSJean-Christophe PLAGNIOL-VILLARD int ret_val = 0; 29572439e4bfSJean-Christophe PLAGNIOL-VILLARD 29582439e4bfSJean-Christophe PLAGNIOL-VILLARD ret_val = e1000_reset(nic); 29592439e4bfSJean-Christophe PLAGNIOL-VILLARD if (ret_val < 0) { 29602439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((ret_val == -E1000_ERR_NOLINK) || 29612439e4bfSJean-Christophe PLAGNIOL-VILLARD (ret_val == -E1000_ERR_TIMEOUT)) { 29622439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_ERR("Valid Link not detected\n"); 29632439e4bfSJean-Christophe PLAGNIOL-VILLARD } else { 29642439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_ERR("Hardware Initialization Failed\n"); 29652439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29662439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 29672439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29682439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_configure_tx(hw); 29692439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_setup_rctl(hw); 29702439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_configure_rx(hw); 29712439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 29722439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29732439e4bfSJean-Christophe PLAGNIOL-VILLARD 29742439e4bfSJean-Christophe PLAGNIOL-VILLARD /************************************************************************** 29752439e4bfSJean-Christophe PLAGNIOL-VILLARD PROBE - Look for an adapter, this routine's visible to the outside 29762439e4bfSJean-Christophe PLAGNIOL-VILLARD You should omit the last argument struct pci_device * for a non-PCI NIC 29772439e4bfSJean-Christophe PLAGNIOL-VILLARD ***************************************************************************/ 29782439e4bfSJean-Christophe PLAGNIOL-VILLARD int 29792439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_initialize(bd_t * bis) 29802439e4bfSJean-Christophe PLAGNIOL-VILLARD { 29812439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_dev_t devno; 29822439e4bfSJean-Christophe PLAGNIOL-VILLARD int card_number = 0; 29832439e4bfSJean-Christophe PLAGNIOL-VILLARD struct eth_device *nic = NULL; 29842439e4bfSJean-Christophe PLAGNIOL-VILLARD struct e1000_hw *hw = NULL; 29852439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 iobase; 29862439e4bfSJean-Christophe PLAGNIOL-VILLARD int idx = 0; 29872439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 PciCommandWord; 29882439e4bfSJean-Christophe PLAGNIOL-VILLARD 29892439e4bfSJean-Christophe PLAGNIOL-VILLARD while (1) { /* Find PCI device(s) */ 29902439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((devno = pci_find_devices(supported, idx++)) < 0) { 29912439e4bfSJean-Christophe PLAGNIOL-VILLARD break; 29922439e4bfSJean-Christophe PLAGNIOL-VILLARD } 29932439e4bfSJean-Christophe PLAGNIOL-VILLARD 29942439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); 29952439e4bfSJean-Christophe PLAGNIOL-VILLARD iobase &= ~0xf; /* Mask the bits that say "this is an io addr" */ 29962439e4bfSJean-Christophe PLAGNIOL-VILLARD DEBUGOUT("e1000#%d: iobase 0x%08x\n", card_number, iobase); 29972439e4bfSJean-Christophe PLAGNIOL-VILLARD 29982439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_write_config_dword(devno, PCI_COMMAND, 29992439e4bfSJean-Christophe PLAGNIOL-VILLARD PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 30002439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Check if I/O accesses and Bus Mastering are enabled. */ 30012439e4bfSJean-Christophe PLAGNIOL-VILLARD pci_read_config_dword(devno, PCI_COMMAND, &PciCommandWord); 30022439e4bfSJean-Christophe PLAGNIOL-VILLARD if (!(PciCommandWord & PCI_COMMAND_MEMORY)) { 30032439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Error: Can not enable MEM access.\n"); 30042439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 30052439e4bfSJean-Christophe PLAGNIOL-VILLARD } else if (!(PciCommandWord & PCI_COMMAND_MASTER)) { 30062439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("Error: Can not enable Bus Mastering.\n"); 30072439e4bfSJean-Christophe PLAGNIOL-VILLARD continue; 30082439e4bfSJean-Christophe PLAGNIOL-VILLARD } 30092439e4bfSJean-Christophe PLAGNIOL-VILLARD 30102439e4bfSJean-Christophe PLAGNIOL-VILLARD nic = (struct eth_device *) malloc(sizeof (*nic)); 30112439e4bfSJean-Christophe PLAGNIOL-VILLARD hw = (struct e1000_hw *) malloc(sizeof (*hw)); 30122439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->pdev = devno; 30132439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->priv = hw; 30142439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->iobase = bus_to_phys(devno, iobase); 30152439e4bfSJean-Christophe PLAGNIOL-VILLARD 30162439e4bfSJean-Christophe PLAGNIOL-VILLARD sprintf(nic->name, "e1000#%d", card_number); 30172439e4bfSJean-Christophe PLAGNIOL-VILLARD 30182439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Are these variables needed? */ 30192439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0 30202439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_none; 30212439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->original_fc = e1000_fc_none; 30222439e4bfSJean-Christophe PLAGNIOL-VILLARD #else 30232439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->fc = e1000_fc_default; 30242439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->original_fc = e1000_fc_default; 30252439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 30262439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->autoneg_failed = 0; 30272439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->get_link_status = TRUE; 30282439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->hw_addr = (typeof(hw->hw_addr)) iobase; 30292439e4bfSJean-Christophe PLAGNIOL-VILLARD hw->mac_type = e1000_undefined; 30302439e4bfSJean-Christophe PLAGNIOL-VILLARD 30312439e4bfSJean-Christophe PLAGNIOL-VILLARD /* MAC and Phy settings */ 30322439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_sw_init(nic, card_number) < 0) { 30332439e4bfSJean-Christophe PLAGNIOL-VILLARD free(hw); 30342439e4bfSJean-Christophe PLAGNIOL-VILLARD free(nic); 30352439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 30362439e4bfSJean-Christophe PLAGNIOL-VILLARD } 3037ac3315c2SAndre Schwarz #if !(defined(CONFIG_AP1000) || defined(CONFIG_MVBC_1G)) 30382439e4bfSJean-Christophe PLAGNIOL-VILLARD if (e1000_validate_eeprom_checksum(nic) < 0) { 30392439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("The EEPROM Checksum Is Not Valid\n"); 30402439e4bfSJean-Christophe PLAGNIOL-VILLARD free(hw); 30412439e4bfSJean-Christophe PLAGNIOL-VILLARD free(nic); 30422439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0; 30432439e4bfSJean-Christophe PLAGNIOL-VILLARD } 30442439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 30452439e4bfSJean-Christophe PLAGNIOL-VILLARD e1000_read_mac_addr(nic); 30462439e4bfSJean-Christophe PLAGNIOL-VILLARD 30472439e4bfSJean-Christophe PLAGNIOL-VILLARD E1000_WRITE_REG(hw, PBA, E1000_DEFAULT_PBA); 30482439e4bfSJean-Christophe PLAGNIOL-VILLARD 30492439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n", 30502439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2], 30512439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]); 30522439e4bfSJean-Christophe PLAGNIOL-VILLARD 30532439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->init = e1000_init; 30542439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->recv = e1000_poll; 30552439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->send = e1000_transmit; 30562439e4bfSJean-Christophe PLAGNIOL-VILLARD nic->halt = e1000_disable; 30572439e4bfSJean-Christophe PLAGNIOL-VILLARD 30582439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_register(nic); 30592439e4bfSJean-Christophe PLAGNIOL-VILLARD 30602439e4bfSJean-Christophe PLAGNIOL-VILLARD card_number++; 30612439e4bfSJean-Christophe PLAGNIOL-VILLARD } 30622439e4bfSJean-Christophe PLAGNIOL-VILLARD return 1; 30632439e4bfSJean-Christophe PLAGNIOL-VILLARD } 30642439e4bfSJean-Christophe PLAGNIOL-VILLARD 30652439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif 3066