1*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
2*8044SWilliam.Kucharski@Sun.COM Etherboot - BOOTP/TFTP Bootstrap Program
3*8044SWilliam.Kucharski@Sun.COM Inter Pro 1000 for Etherboot
4*8044SWilliam.Kucharski@Sun.COM Drivers are port from Intel's Linux driver e1000-4.3.15
5*8044SWilliam.Kucharski@Sun.COM
6*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
7*8044SWilliam.Kucharski@Sun.COM /*******************************************************************************
8*8044SWilliam.Kucharski@Sun.COM
9*8044SWilliam.Kucharski@Sun.COM
10*8044SWilliam.Kucharski@Sun.COM Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
11*8044SWilliam.Kucharski@Sun.COM
12*8044SWilliam.Kucharski@Sun.COM This program is free software; you can redistribute it and/or modify it
13*8044SWilliam.Kucharski@Sun.COM under the terms of the GNU General Public License as published by the Free
14*8044SWilliam.Kucharski@Sun.COM Software Foundation; either version 2 of the License, or (at your option)
15*8044SWilliam.Kucharski@Sun.COM any later version.
16*8044SWilliam.Kucharski@Sun.COM
17*8044SWilliam.Kucharski@Sun.COM This program is distributed in the hope that it will be useful, but WITHOUT
18*8044SWilliam.Kucharski@Sun.COM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19*8044SWilliam.Kucharski@Sun.COM FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20*8044SWilliam.Kucharski@Sun.COM more details.
21*8044SWilliam.Kucharski@Sun.COM
22*8044SWilliam.Kucharski@Sun.COM You should have received a copy of the GNU General Public License along with
23*8044SWilliam.Kucharski@Sun.COM this program; if not, write to the Free Software Foundation, Inc., 59
24*8044SWilliam.Kucharski@Sun.COM Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25*8044SWilliam.Kucharski@Sun.COM
26*8044SWilliam.Kucharski@Sun.COM The full GNU General Public License is included in this distribution in the
27*8044SWilliam.Kucharski@Sun.COM file called LICENSE.
28*8044SWilliam.Kucharski@Sun.COM
29*8044SWilliam.Kucharski@Sun.COM Contact Information:
30*8044SWilliam.Kucharski@Sun.COM Linux NICS <linux.nics@intel.com>
31*8044SWilliam.Kucharski@Sun.COM Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
32*8044SWilliam.Kucharski@Sun.COM
33*8044SWilliam.Kucharski@Sun.COM *******************************************************************************/
34*8044SWilliam.Kucharski@Sun.COM /*
35*8044SWilliam.Kucharski@Sun.COM * Copyright (C) Archway Digital Solutions.
36*8044SWilliam.Kucharski@Sun.COM *
37*8044SWilliam.Kucharski@Sun.COM * written by Chrsitopher Li <cli at arcyway dot com> or <chrisl at gnuchina dot org>
38*8044SWilliam.Kucharski@Sun.COM * 2/9/2002
39*8044SWilliam.Kucharski@Sun.COM *
40*8044SWilliam.Kucharski@Sun.COM * Copyright (C) Linux Networx.
41*8044SWilliam.Kucharski@Sun.COM * Massive upgrade to work with the new intel gigabit NICs.
42*8044SWilliam.Kucharski@Sun.COM * <ebiederman at lnxi dot com>
43*8044SWilliam.Kucharski@Sun.COM *
44*8044SWilliam.Kucharski@Sun.COM * Support for 82541ei & 82547ei chips from Intel's Linux driver 5.1.13 added by
45*8044SWilliam.Kucharski@Sun.COM * Georg Baum <gbaum@users.sf.net>, sponsored by PetaMem GmbH and linkLINE Communications, Inc.
46*8044SWilliam.Kucharski@Sun.COM *
47*8044SWilliam.Kucharski@Sun.COM * 01/2004: Updated to Linux driver 5.2.22 by Georg Baum <gbaum@users.sf.net>
48*8044SWilliam.Kucharski@Sun.COM */
49*8044SWilliam.Kucharski@Sun.COM
50*8044SWilliam.Kucharski@Sun.COM /* to get some global routines like printf */
51*8044SWilliam.Kucharski@Sun.COM #include "etherboot.h"
52*8044SWilliam.Kucharski@Sun.COM /* to get the interface to the body of the program */
53*8044SWilliam.Kucharski@Sun.COM #include "nic.h"
54*8044SWilliam.Kucharski@Sun.COM /* to get the PCI support functions, if this is a PCI NIC */
55*8044SWilliam.Kucharski@Sun.COM #include "pci.h"
56*8044SWilliam.Kucharski@Sun.COM #include "timer.h"
57*8044SWilliam.Kucharski@Sun.COM
58*8044SWilliam.Kucharski@Sun.COM typedef unsigned char *dma_addr_t;
59*8044SWilliam.Kucharski@Sun.COM
60*8044SWilliam.Kucharski@Sun.COM typedef enum {
61*8044SWilliam.Kucharski@Sun.COM FALSE = 0,
62*8044SWilliam.Kucharski@Sun.COM TRUE = 1
63*8044SWilliam.Kucharski@Sun.COM } boolean_t;
64*8044SWilliam.Kucharski@Sun.COM
65*8044SWilliam.Kucharski@Sun.COM #define DEBUG 0
66*8044SWilliam.Kucharski@Sun.COM
67*8044SWilliam.Kucharski@Sun.COM
68*8044SWilliam.Kucharski@Sun.COM /* Some pieces of code are disabled with #if 0 ... #endif.
69*8044SWilliam.Kucharski@Sun.COM * They are not deleted to show where the etherboot driver differs
70*8044SWilliam.Kucharski@Sun.COM * from the linux driver below the function level.
71*8044SWilliam.Kucharski@Sun.COM * Some member variables of the hw struct have been eliminated
72*8044SWilliam.Kucharski@Sun.COM * and the corresponding inplace checks inserted instead.
73*8044SWilliam.Kucharski@Sun.COM * Pieces such as LED handling that we definitely don't need are deleted.
74*8044SWilliam.Kucharski@Sun.COM *
75*8044SWilliam.Kucharski@Sun.COM * The following defines should not be needed normally,
76*8044SWilliam.Kucharski@Sun.COM * but may be helpful for debugging purposes. */
77*8044SWilliam.Kucharski@Sun.COM
78*8044SWilliam.Kucharski@Sun.COM /* Define this if you want to program the transmission control register
79*8044SWilliam.Kucharski@Sun.COM * the way the Linux driver does it. */
80*8044SWilliam.Kucharski@Sun.COM #undef LINUX_DRIVER_TCTL
81*8044SWilliam.Kucharski@Sun.COM
82*8044SWilliam.Kucharski@Sun.COM /* Define this to behave more like the Linux driver. */
83*8044SWilliam.Kucharski@Sun.COM #undef LINUX_DRIVER
84*8044SWilliam.Kucharski@Sun.COM
85*8044SWilliam.Kucharski@Sun.COM #include "e1000_hw.h"
86*8044SWilliam.Kucharski@Sun.COM
87*8044SWilliam.Kucharski@Sun.COM /* NIC specific static variables go here */
88*8044SWilliam.Kucharski@Sun.COM static struct e1000_hw hw;
89*8044SWilliam.Kucharski@Sun.COM static char tx_pool[128 + 16];
90*8044SWilliam.Kucharski@Sun.COM static char rx_pool[128 + 16];
91*8044SWilliam.Kucharski@Sun.COM static char packet[2096];
92*8044SWilliam.Kucharski@Sun.COM
93*8044SWilliam.Kucharski@Sun.COM static struct e1000_tx_desc *tx_base;
94*8044SWilliam.Kucharski@Sun.COM static struct e1000_rx_desc *rx_base;
95*8044SWilliam.Kucharski@Sun.COM
96*8044SWilliam.Kucharski@Sun.COM static int tx_tail;
97*8044SWilliam.Kucharski@Sun.COM static int rx_tail, rx_last;
98*8044SWilliam.Kucharski@Sun.COM
99*8044SWilliam.Kucharski@Sun.COM /* Function forward declarations */
100*8044SWilliam.Kucharski@Sun.COM static int e1000_setup_link(struct e1000_hw *hw);
101*8044SWilliam.Kucharski@Sun.COM static int e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
102*8044SWilliam.Kucharski@Sun.COM static int e1000_setup_copper_link(struct e1000_hw *hw);
103*8044SWilliam.Kucharski@Sun.COM static int e1000_phy_setup_autoneg(struct e1000_hw *hw);
104*8044SWilliam.Kucharski@Sun.COM static void e1000_config_collision_dist(struct e1000_hw *hw);
105*8044SWilliam.Kucharski@Sun.COM static int e1000_config_mac_to_phy(struct e1000_hw *hw);
106*8044SWilliam.Kucharski@Sun.COM static int e1000_config_fc_after_link_up(struct e1000_hw *hw);
107*8044SWilliam.Kucharski@Sun.COM static int e1000_check_for_link(struct e1000_hw *hw);
108*8044SWilliam.Kucharski@Sun.COM static int e1000_wait_autoneg(struct e1000_hw *hw);
109*8044SWilliam.Kucharski@Sun.COM static void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex);
110*8044SWilliam.Kucharski@Sun.COM static int e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
111*8044SWilliam.Kucharski@Sun.COM static int e1000_read_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
112*8044SWilliam.Kucharski@Sun.COM static int e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t phy_data);
113*8044SWilliam.Kucharski@Sun.COM static int e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr, uint16_t phy_data);
114*8044SWilliam.Kucharski@Sun.COM static void e1000_phy_hw_reset(struct e1000_hw *hw);
115*8044SWilliam.Kucharski@Sun.COM static int e1000_phy_reset(struct e1000_hw *hw);
116*8044SWilliam.Kucharski@Sun.COM static int e1000_detect_gig_phy(struct e1000_hw *hw);
117*8044SWilliam.Kucharski@Sun.COM
118*8044SWilliam.Kucharski@Sun.COM /* Printing macros... */
119*8044SWilliam.Kucharski@Sun.COM
120*8044SWilliam.Kucharski@Sun.COM #define E1000_ERR(args...) printf("e1000: " args)
121*8044SWilliam.Kucharski@Sun.COM
122*8044SWilliam.Kucharski@Sun.COM #if DEBUG >= 3
123*8044SWilliam.Kucharski@Sun.COM #define E1000_DBG(args...) printf("e1000: " args)
124*8044SWilliam.Kucharski@Sun.COM #else
125*8044SWilliam.Kucharski@Sun.COM #define E1000_DBG(args...)
126*8044SWilliam.Kucharski@Sun.COM #endif
127*8044SWilliam.Kucharski@Sun.COM
128*8044SWilliam.Kucharski@Sun.COM #define MSGOUT(S, A, B) printk(S "\n", A, B)
129*8044SWilliam.Kucharski@Sun.COM #if DEBUG >= 2
130*8044SWilliam.Kucharski@Sun.COM #define DEBUGFUNC(F) DEBUGOUT(F "\n");
131*8044SWilliam.Kucharski@Sun.COM #else
132*8044SWilliam.Kucharski@Sun.COM #define DEBUGFUNC(F)
133*8044SWilliam.Kucharski@Sun.COM #endif
134*8044SWilliam.Kucharski@Sun.COM #if DEBUG >= 1
135*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT(S) printf(S)
136*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT1(S,A) printf(S,A)
137*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT2(S,A,B) printf(S,A,B)
138*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT3(S,A,B,C) printf(S,A,B,C)
139*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT7(S,A,B,C,D,E,F,G) printf(S,A,B,C,D,E,F,G)
140*8044SWilliam.Kucharski@Sun.COM #else
141*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT(S)
142*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT1(S,A)
143*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT2(S,A,B)
144*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT3(S,A,B,C)
145*8044SWilliam.Kucharski@Sun.COM #define DEBUGOUT7(S,A,B,C,D,E,F,G)
146*8044SWilliam.Kucharski@Sun.COM #endif
147*8044SWilliam.Kucharski@Sun.COM
148*8044SWilliam.Kucharski@Sun.COM #define E1000_WRITE_REG(a, reg, value) ( \
149*8044SWilliam.Kucharski@Sun.COM ((a)->mac_type >= e1000_82543) ? \
150*8044SWilliam.Kucharski@Sun.COM (writel((value), ((a)->hw_addr + E1000_##reg))) : \
151*8044SWilliam.Kucharski@Sun.COM (writel((value), ((a)->hw_addr + E1000_82542_##reg))))
152*8044SWilliam.Kucharski@Sun.COM
153*8044SWilliam.Kucharski@Sun.COM #define E1000_READ_REG(a, reg) ( \
154*8044SWilliam.Kucharski@Sun.COM ((a)->mac_type >= e1000_82543) ? \
155*8044SWilliam.Kucharski@Sun.COM readl((a)->hw_addr + E1000_##reg) : \
156*8044SWilliam.Kucharski@Sun.COM readl((a)->hw_addr + E1000_82542_##reg))
157*8044SWilliam.Kucharski@Sun.COM
158*8044SWilliam.Kucharski@Sun.COM #define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
159*8044SWilliam.Kucharski@Sun.COM ((a)->mac_type >= e1000_82543) ? \
160*8044SWilliam.Kucharski@Sun.COM writel((value), ((a)->hw_addr + E1000_##reg + ((offset) << 2))) : \
161*8044SWilliam.Kucharski@Sun.COM writel((value), ((a)->hw_addr + E1000_82542_##reg + ((offset) << 2))))
162*8044SWilliam.Kucharski@Sun.COM
163*8044SWilliam.Kucharski@Sun.COM #define E1000_READ_REG_ARRAY(a, reg, offset) ( \
164*8044SWilliam.Kucharski@Sun.COM ((a)->mac_type >= e1000_82543) ? \
165*8044SWilliam.Kucharski@Sun.COM readl((a)->hw_addr + E1000_##reg + ((offset) << 2)) : \
166*8044SWilliam.Kucharski@Sun.COM readl((a)->hw_addr + E1000_82542_##reg + ((offset) << 2)))
167*8044SWilliam.Kucharski@Sun.COM
168*8044SWilliam.Kucharski@Sun.COM #define E1000_WRITE_FLUSH(a) {uint32_t x; x = E1000_READ_REG(a, STATUS);}
169*8044SWilliam.Kucharski@Sun.COM
170*8044SWilliam.Kucharski@Sun.COM uint32_t
e1000_io_read(struct e1000_hw * hw __unused,uint32_t port)171*8044SWilliam.Kucharski@Sun.COM e1000_io_read(struct e1000_hw *hw __unused, uint32_t port)
172*8044SWilliam.Kucharski@Sun.COM {
173*8044SWilliam.Kucharski@Sun.COM return inl(port);
174*8044SWilliam.Kucharski@Sun.COM }
175*8044SWilliam.Kucharski@Sun.COM
176*8044SWilliam.Kucharski@Sun.COM void
e1000_io_write(struct e1000_hw * hw __unused,uint32_t port,uint32_t value)177*8044SWilliam.Kucharski@Sun.COM e1000_io_write(struct e1000_hw *hw __unused, uint32_t port, uint32_t value)
178*8044SWilliam.Kucharski@Sun.COM {
179*8044SWilliam.Kucharski@Sun.COM outl(value, port);
180*8044SWilliam.Kucharski@Sun.COM }
181*8044SWilliam.Kucharski@Sun.COM
e1000_pci_set_mwi(struct e1000_hw * hw)182*8044SWilliam.Kucharski@Sun.COM static inline void e1000_pci_set_mwi(struct e1000_hw *hw)
183*8044SWilliam.Kucharski@Sun.COM {
184*8044SWilliam.Kucharski@Sun.COM pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word);
185*8044SWilliam.Kucharski@Sun.COM }
186*8044SWilliam.Kucharski@Sun.COM
e1000_pci_clear_mwi(struct e1000_hw * hw)187*8044SWilliam.Kucharski@Sun.COM static inline void e1000_pci_clear_mwi(struct e1000_hw *hw)
188*8044SWilliam.Kucharski@Sun.COM {
189*8044SWilliam.Kucharski@Sun.COM pci_write_config_word(hw->pdev, PCI_COMMAND,
190*8044SWilliam.Kucharski@Sun.COM hw->pci_cmd_word & ~PCI_COMMAND_INVALIDATE);
191*8044SWilliam.Kucharski@Sun.COM }
192*8044SWilliam.Kucharski@Sun.COM
193*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
194*8044SWilliam.Kucharski@Sun.COM * Raises the EEPROM's clock input.
195*8044SWilliam.Kucharski@Sun.COM *
196*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
197*8044SWilliam.Kucharski@Sun.COM * eecd - EECD's current value
198*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
199*8044SWilliam.Kucharski@Sun.COM static void
e1000_raise_ee_clk(struct e1000_hw * hw,uint32_t * eecd)200*8044SWilliam.Kucharski@Sun.COM e1000_raise_ee_clk(struct e1000_hw *hw,
201*8044SWilliam.Kucharski@Sun.COM uint32_t *eecd)
202*8044SWilliam.Kucharski@Sun.COM {
203*8044SWilliam.Kucharski@Sun.COM /* Raise the clock input to the EEPROM (by setting the SK bit), and then
204*8044SWilliam.Kucharski@Sun.COM * wait <delay> microseconds.
205*8044SWilliam.Kucharski@Sun.COM */
206*8044SWilliam.Kucharski@Sun.COM *eecd = *eecd | E1000_EECD_SK;
207*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, *eecd);
208*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
209*8044SWilliam.Kucharski@Sun.COM udelay(hw->eeprom.delay_usec);
210*8044SWilliam.Kucharski@Sun.COM }
211*8044SWilliam.Kucharski@Sun.COM
212*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
213*8044SWilliam.Kucharski@Sun.COM * Lowers the EEPROM's clock input.
214*8044SWilliam.Kucharski@Sun.COM *
215*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
216*8044SWilliam.Kucharski@Sun.COM * eecd - EECD's current value
217*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
218*8044SWilliam.Kucharski@Sun.COM static void
e1000_lower_ee_clk(struct e1000_hw * hw,uint32_t * eecd)219*8044SWilliam.Kucharski@Sun.COM e1000_lower_ee_clk(struct e1000_hw *hw,
220*8044SWilliam.Kucharski@Sun.COM uint32_t *eecd)
221*8044SWilliam.Kucharski@Sun.COM {
222*8044SWilliam.Kucharski@Sun.COM /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
223*8044SWilliam.Kucharski@Sun.COM * wait 50 microseconds.
224*8044SWilliam.Kucharski@Sun.COM */
225*8044SWilliam.Kucharski@Sun.COM *eecd = *eecd & ~E1000_EECD_SK;
226*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, *eecd);
227*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
228*8044SWilliam.Kucharski@Sun.COM udelay(hw->eeprom.delay_usec);
229*8044SWilliam.Kucharski@Sun.COM }
230*8044SWilliam.Kucharski@Sun.COM
231*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
232*8044SWilliam.Kucharski@Sun.COM * Shift data bits out to the EEPROM.
233*8044SWilliam.Kucharski@Sun.COM *
234*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
235*8044SWilliam.Kucharski@Sun.COM * data - data to send to the EEPROM
236*8044SWilliam.Kucharski@Sun.COM * count - number of bits to shift out
237*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
238*8044SWilliam.Kucharski@Sun.COM static void
e1000_shift_out_ee_bits(struct e1000_hw * hw,uint16_t data,uint16_t count)239*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_ee_bits(struct e1000_hw *hw,
240*8044SWilliam.Kucharski@Sun.COM uint16_t data,
241*8044SWilliam.Kucharski@Sun.COM uint16_t count)
242*8044SWilliam.Kucharski@Sun.COM {
243*8044SWilliam.Kucharski@Sun.COM struct e1000_eeprom_info *eeprom = &hw->eeprom;
244*8044SWilliam.Kucharski@Sun.COM uint32_t eecd;
245*8044SWilliam.Kucharski@Sun.COM uint32_t mask;
246*8044SWilliam.Kucharski@Sun.COM
247*8044SWilliam.Kucharski@Sun.COM /* We need to shift "count" bits out to the EEPROM. So, value in the
248*8044SWilliam.Kucharski@Sun.COM * "data" parameter will be shifted out to the EEPROM one bit at a time.
249*8044SWilliam.Kucharski@Sun.COM * In order to do this, "data" must be broken down into bits.
250*8044SWilliam.Kucharski@Sun.COM */
251*8044SWilliam.Kucharski@Sun.COM mask = 0x01 << (count - 1);
252*8044SWilliam.Kucharski@Sun.COM eecd = E1000_READ_REG(hw, EECD);
253*8044SWilliam.Kucharski@Sun.COM if (eeprom->type == e1000_eeprom_microwire) {
254*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_DO;
255*8044SWilliam.Kucharski@Sun.COM } else if (eeprom->type == e1000_eeprom_spi) {
256*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_DO;
257*8044SWilliam.Kucharski@Sun.COM }
258*8044SWilliam.Kucharski@Sun.COM do {
259*8044SWilliam.Kucharski@Sun.COM /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
260*8044SWilliam.Kucharski@Sun.COM * and then raising and then lowering the clock (the SK bit controls
261*8044SWilliam.Kucharski@Sun.COM * the clock input to the EEPROM). A "0" is shifted out to the EEPROM
262*8044SWilliam.Kucharski@Sun.COM * by setting "DI" to "0" and then raising and then lowering the clock.
263*8044SWilliam.Kucharski@Sun.COM */
264*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_DI;
265*8044SWilliam.Kucharski@Sun.COM
266*8044SWilliam.Kucharski@Sun.COM if(data & mask)
267*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_DI;
268*8044SWilliam.Kucharski@Sun.COM
269*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
270*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
271*8044SWilliam.Kucharski@Sun.COM
272*8044SWilliam.Kucharski@Sun.COM udelay(eeprom->delay_usec);
273*8044SWilliam.Kucharski@Sun.COM
274*8044SWilliam.Kucharski@Sun.COM e1000_raise_ee_clk(hw, &eecd);
275*8044SWilliam.Kucharski@Sun.COM e1000_lower_ee_clk(hw, &eecd);
276*8044SWilliam.Kucharski@Sun.COM
277*8044SWilliam.Kucharski@Sun.COM mask = mask >> 1;
278*8044SWilliam.Kucharski@Sun.COM
279*8044SWilliam.Kucharski@Sun.COM } while(mask);
280*8044SWilliam.Kucharski@Sun.COM
281*8044SWilliam.Kucharski@Sun.COM /* We leave the "DI" bit set to "0" when we leave this routine. */
282*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_DI;
283*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
284*8044SWilliam.Kucharski@Sun.COM }
285*8044SWilliam.Kucharski@Sun.COM
286*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
287*8044SWilliam.Kucharski@Sun.COM * Shift data bits in from the EEPROM
288*8044SWilliam.Kucharski@Sun.COM *
289*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
290*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
291*8044SWilliam.Kucharski@Sun.COM static uint16_t
e1000_shift_in_ee_bits(struct e1000_hw * hw,uint16_t count)292*8044SWilliam.Kucharski@Sun.COM e1000_shift_in_ee_bits(struct e1000_hw *hw,
293*8044SWilliam.Kucharski@Sun.COM uint16_t count)
294*8044SWilliam.Kucharski@Sun.COM {
295*8044SWilliam.Kucharski@Sun.COM uint32_t eecd;
296*8044SWilliam.Kucharski@Sun.COM uint32_t i;
297*8044SWilliam.Kucharski@Sun.COM uint16_t data;
298*8044SWilliam.Kucharski@Sun.COM
299*8044SWilliam.Kucharski@Sun.COM /* In order to read a register from the EEPROM, we need to shift 'count'
300*8044SWilliam.Kucharski@Sun.COM * bits in from the EEPROM. Bits are "shifted in" by raising the clock
301*8044SWilliam.Kucharski@Sun.COM * input to the EEPROM (setting the SK bit), and then reading the value of
302*8044SWilliam.Kucharski@Sun.COM * the "DO" bit. During this "shifting in" process the "DI" bit should
303*8044SWilliam.Kucharski@Sun.COM * always be clear.
304*8044SWilliam.Kucharski@Sun.COM */
305*8044SWilliam.Kucharski@Sun.COM
306*8044SWilliam.Kucharski@Sun.COM eecd = E1000_READ_REG(hw, EECD);
307*8044SWilliam.Kucharski@Sun.COM
308*8044SWilliam.Kucharski@Sun.COM eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
309*8044SWilliam.Kucharski@Sun.COM data = 0;
310*8044SWilliam.Kucharski@Sun.COM
311*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < count; i++) {
312*8044SWilliam.Kucharski@Sun.COM data = data << 1;
313*8044SWilliam.Kucharski@Sun.COM e1000_raise_ee_clk(hw, &eecd);
314*8044SWilliam.Kucharski@Sun.COM
315*8044SWilliam.Kucharski@Sun.COM eecd = E1000_READ_REG(hw, EECD);
316*8044SWilliam.Kucharski@Sun.COM
317*8044SWilliam.Kucharski@Sun.COM eecd &= ~(E1000_EECD_DI);
318*8044SWilliam.Kucharski@Sun.COM if(eecd & E1000_EECD_DO)
319*8044SWilliam.Kucharski@Sun.COM data |= 1;
320*8044SWilliam.Kucharski@Sun.COM
321*8044SWilliam.Kucharski@Sun.COM e1000_lower_ee_clk(hw, &eecd);
322*8044SWilliam.Kucharski@Sun.COM }
323*8044SWilliam.Kucharski@Sun.COM
324*8044SWilliam.Kucharski@Sun.COM return data;
325*8044SWilliam.Kucharski@Sun.COM }
326*8044SWilliam.Kucharski@Sun.COM
327*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
328*8044SWilliam.Kucharski@Sun.COM * Prepares EEPROM for access
329*8044SWilliam.Kucharski@Sun.COM *
330*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
331*8044SWilliam.Kucharski@Sun.COM *
332*8044SWilliam.Kucharski@Sun.COM * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
333*8044SWilliam.Kucharski@Sun.COM * function should be called before issuing a command to the EEPROM.
334*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
335*8044SWilliam.Kucharski@Sun.COM static int32_t
e1000_acquire_eeprom(struct e1000_hw * hw)336*8044SWilliam.Kucharski@Sun.COM e1000_acquire_eeprom(struct e1000_hw *hw)
337*8044SWilliam.Kucharski@Sun.COM {
338*8044SWilliam.Kucharski@Sun.COM struct e1000_eeprom_info *eeprom = &hw->eeprom;
339*8044SWilliam.Kucharski@Sun.COM uint32_t eecd, i=0;
340*8044SWilliam.Kucharski@Sun.COM
341*8044SWilliam.Kucharski@Sun.COM eecd = E1000_READ_REG(hw, EECD);
342*8044SWilliam.Kucharski@Sun.COM
343*8044SWilliam.Kucharski@Sun.COM /* Request EEPROM Access */
344*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type > e1000_82544) {
345*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_REQ;
346*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
347*8044SWilliam.Kucharski@Sun.COM eecd = E1000_READ_REG(hw, EECD);
348*8044SWilliam.Kucharski@Sun.COM while((!(eecd & E1000_EECD_GNT)) &&
349*8044SWilliam.Kucharski@Sun.COM (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
350*8044SWilliam.Kucharski@Sun.COM i++;
351*8044SWilliam.Kucharski@Sun.COM udelay(5);
352*8044SWilliam.Kucharski@Sun.COM eecd = E1000_READ_REG(hw, EECD);
353*8044SWilliam.Kucharski@Sun.COM }
354*8044SWilliam.Kucharski@Sun.COM if(!(eecd & E1000_EECD_GNT)) {
355*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_REQ;
356*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
357*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Could not acquire EEPROM grant\n");
358*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
359*8044SWilliam.Kucharski@Sun.COM }
360*8044SWilliam.Kucharski@Sun.COM }
361*8044SWilliam.Kucharski@Sun.COM
362*8044SWilliam.Kucharski@Sun.COM /* Setup EEPROM for Read/Write */
363*8044SWilliam.Kucharski@Sun.COM
364*8044SWilliam.Kucharski@Sun.COM if (eeprom->type == e1000_eeprom_microwire) {
365*8044SWilliam.Kucharski@Sun.COM /* Clear SK and DI */
366*8044SWilliam.Kucharski@Sun.COM eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
367*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
368*8044SWilliam.Kucharski@Sun.COM
369*8044SWilliam.Kucharski@Sun.COM /* Set CS */
370*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_CS;
371*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
372*8044SWilliam.Kucharski@Sun.COM } else if (eeprom->type == e1000_eeprom_spi) {
373*8044SWilliam.Kucharski@Sun.COM /* Clear SK and CS */
374*8044SWilliam.Kucharski@Sun.COM eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
375*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
376*8044SWilliam.Kucharski@Sun.COM udelay(1);
377*8044SWilliam.Kucharski@Sun.COM }
378*8044SWilliam.Kucharski@Sun.COM
379*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
380*8044SWilliam.Kucharski@Sun.COM }
381*8044SWilliam.Kucharski@Sun.COM
382*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
383*8044SWilliam.Kucharski@Sun.COM * Returns EEPROM to a "standby" state
384*8044SWilliam.Kucharski@Sun.COM *
385*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
386*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
387*8044SWilliam.Kucharski@Sun.COM static void
e1000_standby_eeprom(struct e1000_hw * hw)388*8044SWilliam.Kucharski@Sun.COM e1000_standby_eeprom(struct e1000_hw *hw)
389*8044SWilliam.Kucharski@Sun.COM {
390*8044SWilliam.Kucharski@Sun.COM struct e1000_eeprom_info *eeprom = &hw->eeprom;
391*8044SWilliam.Kucharski@Sun.COM uint32_t eecd;
392*8044SWilliam.Kucharski@Sun.COM
393*8044SWilliam.Kucharski@Sun.COM eecd = E1000_READ_REG(hw, EECD);
394*8044SWilliam.Kucharski@Sun.COM
395*8044SWilliam.Kucharski@Sun.COM if(eeprom->type == e1000_eeprom_microwire) {
396*8044SWilliam.Kucharski@Sun.COM
397*8044SWilliam.Kucharski@Sun.COM /* Deselect EEPROM */
398*8044SWilliam.Kucharski@Sun.COM eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
399*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
400*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
401*8044SWilliam.Kucharski@Sun.COM udelay(eeprom->delay_usec);
402*8044SWilliam.Kucharski@Sun.COM
403*8044SWilliam.Kucharski@Sun.COM /* Clock high */
404*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_SK;
405*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
406*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
407*8044SWilliam.Kucharski@Sun.COM udelay(eeprom->delay_usec);
408*8044SWilliam.Kucharski@Sun.COM
409*8044SWilliam.Kucharski@Sun.COM /* Select EEPROM */
410*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_CS;
411*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
412*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
413*8044SWilliam.Kucharski@Sun.COM udelay(eeprom->delay_usec);
414*8044SWilliam.Kucharski@Sun.COM
415*8044SWilliam.Kucharski@Sun.COM /* Clock low */
416*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_SK;
417*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
418*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
419*8044SWilliam.Kucharski@Sun.COM udelay(eeprom->delay_usec);
420*8044SWilliam.Kucharski@Sun.COM } else if(eeprom->type == e1000_eeprom_spi) {
421*8044SWilliam.Kucharski@Sun.COM /* Toggle CS to flush commands */
422*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_CS;
423*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
424*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
425*8044SWilliam.Kucharski@Sun.COM udelay(eeprom->delay_usec);
426*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_CS;
427*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
428*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
429*8044SWilliam.Kucharski@Sun.COM udelay(eeprom->delay_usec);
430*8044SWilliam.Kucharski@Sun.COM }
431*8044SWilliam.Kucharski@Sun.COM }
432*8044SWilliam.Kucharski@Sun.COM
433*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
434*8044SWilliam.Kucharski@Sun.COM * Terminates a command by inverting the EEPROM's chip select pin
435*8044SWilliam.Kucharski@Sun.COM *
436*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
437*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
438*8044SWilliam.Kucharski@Sun.COM static void
e1000_release_eeprom(struct e1000_hw * hw)439*8044SWilliam.Kucharski@Sun.COM e1000_release_eeprom(struct e1000_hw *hw)
440*8044SWilliam.Kucharski@Sun.COM {
441*8044SWilliam.Kucharski@Sun.COM uint32_t eecd;
442*8044SWilliam.Kucharski@Sun.COM
443*8044SWilliam.Kucharski@Sun.COM eecd = E1000_READ_REG(hw, EECD);
444*8044SWilliam.Kucharski@Sun.COM
445*8044SWilliam.Kucharski@Sun.COM if (hw->eeprom.type == e1000_eeprom_spi) {
446*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_CS; /* Pull CS high */
447*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_SK; /* Lower SCK */
448*8044SWilliam.Kucharski@Sun.COM
449*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
450*8044SWilliam.Kucharski@Sun.COM
451*8044SWilliam.Kucharski@Sun.COM udelay(hw->eeprom.delay_usec);
452*8044SWilliam.Kucharski@Sun.COM } else if(hw->eeprom.type == e1000_eeprom_microwire) {
453*8044SWilliam.Kucharski@Sun.COM /* cleanup eeprom */
454*8044SWilliam.Kucharski@Sun.COM
455*8044SWilliam.Kucharski@Sun.COM /* CS on Microwire is active-high */
456*8044SWilliam.Kucharski@Sun.COM eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
457*8044SWilliam.Kucharski@Sun.COM
458*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
459*8044SWilliam.Kucharski@Sun.COM
460*8044SWilliam.Kucharski@Sun.COM /* Rising edge of clock */
461*8044SWilliam.Kucharski@Sun.COM eecd |= E1000_EECD_SK;
462*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
463*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
464*8044SWilliam.Kucharski@Sun.COM udelay(hw->eeprom.delay_usec);
465*8044SWilliam.Kucharski@Sun.COM
466*8044SWilliam.Kucharski@Sun.COM /* Falling edge of clock */
467*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_SK;
468*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
469*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
470*8044SWilliam.Kucharski@Sun.COM udelay(hw->eeprom.delay_usec);
471*8044SWilliam.Kucharski@Sun.COM }
472*8044SWilliam.Kucharski@Sun.COM
473*8044SWilliam.Kucharski@Sun.COM /* Stop requesting EEPROM access */
474*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type > e1000_82544) {
475*8044SWilliam.Kucharski@Sun.COM eecd &= ~E1000_EECD_REQ;
476*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, EECD, eecd);
477*8044SWilliam.Kucharski@Sun.COM }
478*8044SWilliam.Kucharski@Sun.COM }
479*8044SWilliam.Kucharski@Sun.COM
480*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
481*8044SWilliam.Kucharski@Sun.COM * Reads a 16 bit word from the EEPROM.
482*8044SWilliam.Kucharski@Sun.COM *
483*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
484*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
485*8044SWilliam.Kucharski@Sun.COM static int32_t
e1000_spi_eeprom_ready(struct e1000_hw * hw)486*8044SWilliam.Kucharski@Sun.COM e1000_spi_eeprom_ready(struct e1000_hw *hw)
487*8044SWilliam.Kucharski@Sun.COM {
488*8044SWilliam.Kucharski@Sun.COM uint16_t retry_count = 0;
489*8044SWilliam.Kucharski@Sun.COM uint8_t spi_stat_reg;
490*8044SWilliam.Kucharski@Sun.COM
491*8044SWilliam.Kucharski@Sun.COM /* Read "Status Register" repeatedly until the LSB is cleared. The
492*8044SWilliam.Kucharski@Sun.COM * EEPROM will signal that the command has been completed by clearing
493*8044SWilliam.Kucharski@Sun.COM * bit 0 of the internal status register. If it's not cleared within
494*8044SWilliam.Kucharski@Sun.COM * 5 milliseconds, then error out.
495*8044SWilliam.Kucharski@Sun.COM */
496*8044SWilliam.Kucharski@Sun.COM retry_count = 0;
497*8044SWilliam.Kucharski@Sun.COM do {
498*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
499*8044SWilliam.Kucharski@Sun.COM hw->eeprom.opcode_bits);
500*8044SWilliam.Kucharski@Sun.COM spi_stat_reg = (uint8_t)e1000_shift_in_ee_bits(hw, 8);
501*8044SWilliam.Kucharski@Sun.COM if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
502*8044SWilliam.Kucharski@Sun.COM break;
503*8044SWilliam.Kucharski@Sun.COM
504*8044SWilliam.Kucharski@Sun.COM udelay(5);
505*8044SWilliam.Kucharski@Sun.COM retry_count += 5;
506*8044SWilliam.Kucharski@Sun.COM
507*8044SWilliam.Kucharski@Sun.COM } while(retry_count < EEPROM_MAX_RETRY_SPI);
508*8044SWilliam.Kucharski@Sun.COM
509*8044SWilliam.Kucharski@Sun.COM /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
510*8044SWilliam.Kucharski@Sun.COM * only 0-5mSec on 5V devices)
511*8044SWilliam.Kucharski@Sun.COM */
512*8044SWilliam.Kucharski@Sun.COM if(retry_count >= EEPROM_MAX_RETRY_SPI) {
513*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("SPI EEPROM Status error\n");
514*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
515*8044SWilliam.Kucharski@Sun.COM }
516*8044SWilliam.Kucharski@Sun.COM
517*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
518*8044SWilliam.Kucharski@Sun.COM }
519*8044SWilliam.Kucharski@Sun.COM
520*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
521*8044SWilliam.Kucharski@Sun.COM * Reads a 16 bit word from the EEPROM.
522*8044SWilliam.Kucharski@Sun.COM *
523*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
524*8044SWilliam.Kucharski@Sun.COM * offset - offset of word in the EEPROM to read
525*8044SWilliam.Kucharski@Sun.COM * data - word read from the EEPROM
526*8044SWilliam.Kucharski@Sun.COM * words - number of words to read
527*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
528*8044SWilliam.Kucharski@Sun.COM static int
e1000_read_eeprom(struct e1000_hw * hw,uint16_t offset,uint16_t words,uint16_t * data)529*8044SWilliam.Kucharski@Sun.COM e1000_read_eeprom(struct e1000_hw *hw,
530*8044SWilliam.Kucharski@Sun.COM uint16_t offset,
531*8044SWilliam.Kucharski@Sun.COM uint16_t words,
532*8044SWilliam.Kucharski@Sun.COM uint16_t *data)
533*8044SWilliam.Kucharski@Sun.COM {
534*8044SWilliam.Kucharski@Sun.COM struct e1000_eeprom_info *eeprom = &hw->eeprom;
535*8044SWilliam.Kucharski@Sun.COM uint32_t i = 0;
536*8044SWilliam.Kucharski@Sun.COM
537*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_read_eeprom");
538*8044SWilliam.Kucharski@Sun.COM
539*8044SWilliam.Kucharski@Sun.COM /* A check for invalid values: offset too large, too many words, and not
540*8044SWilliam.Kucharski@Sun.COM * enough words.
541*8044SWilliam.Kucharski@Sun.COM */
542*8044SWilliam.Kucharski@Sun.COM if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) ||
543*8044SWilliam.Kucharski@Sun.COM (words == 0)) {
544*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("\"words\" parameter out of bounds\n");
545*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
546*8044SWilliam.Kucharski@Sun.COM }
547*8044SWilliam.Kucharski@Sun.COM
548*8044SWilliam.Kucharski@Sun.COM /* Prepare the EEPROM for reading */
549*8044SWilliam.Kucharski@Sun.COM if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
550*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
551*8044SWilliam.Kucharski@Sun.COM
552*8044SWilliam.Kucharski@Sun.COM if(eeprom->type == e1000_eeprom_spi) {
553*8044SWilliam.Kucharski@Sun.COM uint16_t word_in;
554*8044SWilliam.Kucharski@Sun.COM uint8_t read_opcode = EEPROM_READ_OPCODE_SPI;
555*8044SWilliam.Kucharski@Sun.COM
556*8044SWilliam.Kucharski@Sun.COM if(e1000_spi_eeprom_ready(hw)) {
557*8044SWilliam.Kucharski@Sun.COM e1000_release_eeprom(hw);
558*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
559*8044SWilliam.Kucharski@Sun.COM }
560*8044SWilliam.Kucharski@Sun.COM
561*8044SWilliam.Kucharski@Sun.COM e1000_standby_eeprom(hw);
562*8044SWilliam.Kucharski@Sun.COM
563*8044SWilliam.Kucharski@Sun.COM /* Some SPI eeproms use the 8th address bit embedded in the opcode */
564*8044SWilliam.Kucharski@Sun.COM if((eeprom->address_bits == 8) && (offset >= 128))
565*8044SWilliam.Kucharski@Sun.COM read_opcode |= EEPROM_A8_OPCODE_SPI;
566*8044SWilliam.Kucharski@Sun.COM
567*8044SWilliam.Kucharski@Sun.COM /* Send the READ command (opcode + addr) */
568*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
569*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits);
570*8044SWilliam.Kucharski@Sun.COM
571*8044SWilliam.Kucharski@Sun.COM /* Read the data. The address of the eeprom internally increments with
572*8044SWilliam.Kucharski@Sun.COM * each byte (spi) being read, saving on the overhead of eeprom setup
573*8044SWilliam.Kucharski@Sun.COM * and tear-down. The address counter will roll over if reading beyond
574*8044SWilliam.Kucharski@Sun.COM * the size of the eeprom, thus allowing the entire memory to be read
575*8044SWilliam.Kucharski@Sun.COM * starting from any offset. */
576*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < words; i++) {
577*8044SWilliam.Kucharski@Sun.COM word_in = e1000_shift_in_ee_bits(hw, 16);
578*8044SWilliam.Kucharski@Sun.COM data[i] = (word_in >> 8) | (word_in << 8);
579*8044SWilliam.Kucharski@Sun.COM }
580*8044SWilliam.Kucharski@Sun.COM } else if(eeprom->type == e1000_eeprom_microwire) {
581*8044SWilliam.Kucharski@Sun.COM for (i = 0; i < words; i++) {
582*8044SWilliam.Kucharski@Sun.COM /* Send the READ command (opcode + addr) */
583*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE,
584*8044SWilliam.Kucharski@Sun.COM eeprom->opcode_bits);
585*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i),
586*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits);
587*8044SWilliam.Kucharski@Sun.COM
588*8044SWilliam.Kucharski@Sun.COM /* Read the data. For microwire, each word requires the overhead
589*8044SWilliam.Kucharski@Sun.COM * of eeprom setup and tear-down. */
590*8044SWilliam.Kucharski@Sun.COM data[i] = e1000_shift_in_ee_bits(hw, 16);
591*8044SWilliam.Kucharski@Sun.COM e1000_standby_eeprom(hw);
592*8044SWilliam.Kucharski@Sun.COM }
593*8044SWilliam.Kucharski@Sun.COM }
594*8044SWilliam.Kucharski@Sun.COM
595*8044SWilliam.Kucharski@Sun.COM /* End this read operation */
596*8044SWilliam.Kucharski@Sun.COM e1000_release_eeprom(hw);
597*8044SWilliam.Kucharski@Sun.COM
598*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
599*8044SWilliam.Kucharski@Sun.COM }
600*8044SWilliam.Kucharski@Sun.COM
601*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
602*8044SWilliam.Kucharski@Sun.COM * Verifies that the EEPROM has a valid checksum
603*8044SWilliam.Kucharski@Sun.COM *
604*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
605*8044SWilliam.Kucharski@Sun.COM *
606*8044SWilliam.Kucharski@Sun.COM * Reads the first 64 16 bit words of the EEPROM and sums the values read.
607*8044SWilliam.Kucharski@Sun.COM * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
608*8044SWilliam.Kucharski@Sun.COM * valid.
609*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
610*8044SWilliam.Kucharski@Sun.COM static int
e1000_validate_eeprom_checksum(struct e1000_hw * hw)611*8044SWilliam.Kucharski@Sun.COM e1000_validate_eeprom_checksum(struct e1000_hw *hw)
612*8044SWilliam.Kucharski@Sun.COM {
613*8044SWilliam.Kucharski@Sun.COM uint16_t checksum = 0;
614*8044SWilliam.Kucharski@Sun.COM uint16_t i, eeprom_data;
615*8044SWilliam.Kucharski@Sun.COM
616*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_validate_eeprom_checksum");
617*8044SWilliam.Kucharski@Sun.COM
618*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
619*8044SWilliam.Kucharski@Sun.COM if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
620*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("EEPROM Read Error\n");
621*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
622*8044SWilliam.Kucharski@Sun.COM }
623*8044SWilliam.Kucharski@Sun.COM checksum += eeprom_data;
624*8044SWilliam.Kucharski@Sun.COM }
625*8044SWilliam.Kucharski@Sun.COM
626*8044SWilliam.Kucharski@Sun.COM if(checksum == (uint16_t) EEPROM_SUM)
627*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
628*8044SWilliam.Kucharski@Sun.COM else {
629*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("EEPROM Checksum Invalid\n");
630*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
631*8044SWilliam.Kucharski@Sun.COM }
632*8044SWilliam.Kucharski@Sun.COM }
633*8044SWilliam.Kucharski@Sun.COM
634*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
635*8044SWilliam.Kucharski@Sun.COM * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
636*8044SWilliam.Kucharski@Sun.COM * second function of dual function devices
637*8044SWilliam.Kucharski@Sun.COM *
638*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
639*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
640*8044SWilliam.Kucharski@Sun.COM static int
e1000_read_mac_addr(struct e1000_hw * hw)641*8044SWilliam.Kucharski@Sun.COM e1000_read_mac_addr(struct e1000_hw *hw)
642*8044SWilliam.Kucharski@Sun.COM {
643*8044SWilliam.Kucharski@Sun.COM uint16_t offset;
644*8044SWilliam.Kucharski@Sun.COM uint16_t eeprom_data;
645*8044SWilliam.Kucharski@Sun.COM int i;
646*8044SWilliam.Kucharski@Sun.COM
647*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_read_mac_addr");
648*8044SWilliam.Kucharski@Sun.COM
649*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
650*8044SWilliam.Kucharski@Sun.COM offset = i >> 1;
651*8044SWilliam.Kucharski@Sun.COM if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
652*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("EEPROM Read Error\n");
653*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
654*8044SWilliam.Kucharski@Sun.COM }
655*8044SWilliam.Kucharski@Sun.COM hw->mac_addr[i] = eeprom_data & 0xff;
656*8044SWilliam.Kucharski@Sun.COM hw->mac_addr[i+1] = (eeprom_data >> 8) & 0xff;
657*8044SWilliam.Kucharski@Sun.COM }
658*8044SWilliam.Kucharski@Sun.COM if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) &&
659*8044SWilliam.Kucharski@Sun.COM (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1))
660*8044SWilliam.Kucharski@Sun.COM /* Invert the last bit if this is the second device */
661*8044SWilliam.Kucharski@Sun.COM hw->mac_addr[5] ^= 1;
662*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
663*8044SWilliam.Kucharski@Sun.COM }
664*8044SWilliam.Kucharski@Sun.COM
665*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
666*8044SWilliam.Kucharski@Sun.COM * Initializes receive address filters.
667*8044SWilliam.Kucharski@Sun.COM *
668*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
669*8044SWilliam.Kucharski@Sun.COM *
670*8044SWilliam.Kucharski@Sun.COM * Places the MAC address in receive address register 0 and clears the rest
671*8044SWilliam.Kucharski@Sun.COM * of the receive addresss registers. Clears the multicast table. Assumes
672*8044SWilliam.Kucharski@Sun.COM * the receiver is in reset when the routine is called.
673*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
674*8044SWilliam.Kucharski@Sun.COM static void
e1000_init_rx_addrs(struct e1000_hw * hw)675*8044SWilliam.Kucharski@Sun.COM e1000_init_rx_addrs(struct e1000_hw *hw)
676*8044SWilliam.Kucharski@Sun.COM {
677*8044SWilliam.Kucharski@Sun.COM uint32_t i;
678*8044SWilliam.Kucharski@Sun.COM uint32_t addr_low;
679*8044SWilliam.Kucharski@Sun.COM uint32_t addr_high;
680*8044SWilliam.Kucharski@Sun.COM
681*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_init_rx_addrs");
682*8044SWilliam.Kucharski@Sun.COM
683*8044SWilliam.Kucharski@Sun.COM /* Setup the receive address. */
684*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Programming MAC Address into RAR[0]\n");
685*8044SWilliam.Kucharski@Sun.COM addr_low = (hw->mac_addr[0] |
686*8044SWilliam.Kucharski@Sun.COM (hw->mac_addr[1] << 8) |
687*8044SWilliam.Kucharski@Sun.COM (hw->mac_addr[2] << 16) | (hw->mac_addr[3] << 24));
688*8044SWilliam.Kucharski@Sun.COM
689*8044SWilliam.Kucharski@Sun.COM addr_high = (hw->mac_addr[4] |
690*8044SWilliam.Kucharski@Sun.COM (hw->mac_addr[5] << 8) | E1000_RAH_AV);
691*8044SWilliam.Kucharski@Sun.COM
692*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG_ARRAY(hw, RA, 0, addr_low);
693*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG_ARRAY(hw, RA, 1, addr_high);
694*8044SWilliam.Kucharski@Sun.COM
695*8044SWilliam.Kucharski@Sun.COM /* Zero out the other 15 receive addresses. */
696*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Clearing RAR[1-15]\n");
697*8044SWilliam.Kucharski@Sun.COM for(i = 1; i < E1000_RAR_ENTRIES; i++) {
698*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
699*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
700*8044SWilliam.Kucharski@Sun.COM }
701*8044SWilliam.Kucharski@Sun.COM }
702*8044SWilliam.Kucharski@Sun.COM
703*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
704*8044SWilliam.Kucharski@Sun.COM * Clears the VLAN filer table
705*8044SWilliam.Kucharski@Sun.COM *
706*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
707*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
708*8044SWilliam.Kucharski@Sun.COM static void
e1000_clear_vfta(struct e1000_hw * hw)709*8044SWilliam.Kucharski@Sun.COM e1000_clear_vfta(struct e1000_hw *hw)
710*8044SWilliam.Kucharski@Sun.COM {
711*8044SWilliam.Kucharski@Sun.COM uint32_t offset;
712*8044SWilliam.Kucharski@Sun.COM
713*8044SWilliam.Kucharski@Sun.COM for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++)
714*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
715*8044SWilliam.Kucharski@Sun.COM }
716*8044SWilliam.Kucharski@Sun.COM
717*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
718*8044SWilliam.Kucharski@Sun.COM * Writes a value to one of the devices registers using port I/O (as opposed to
719*8044SWilliam.Kucharski@Sun.COM * memory mapped I/O). Only 82544 and newer devices support port I/O. *
720*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
721*8044SWilliam.Kucharski@Sun.COM * offset - offset to write to * value - value to write
722*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
e1000_write_reg_io(struct e1000_hw * hw,uint32_t offset,uint32_t value)723*8044SWilliam.Kucharski@Sun.COM void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value){
724*8044SWilliam.Kucharski@Sun.COM uint32_t io_addr = hw->io_base;
725*8044SWilliam.Kucharski@Sun.COM uint32_t io_data = hw->io_base + 4;
726*8044SWilliam.Kucharski@Sun.COM e1000_io_write(hw, io_addr, offset);
727*8044SWilliam.Kucharski@Sun.COM e1000_io_write(hw, io_data, value);
728*8044SWilliam.Kucharski@Sun.COM }
729*8044SWilliam.Kucharski@Sun.COM
730*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
731*8044SWilliam.Kucharski@Sun.COM * Set the phy type member in the hw struct.
732*8044SWilliam.Kucharski@Sun.COM *
733*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
734*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
735*8044SWilliam.Kucharski@Sun.COM static int32_t
e1000_set_phy_type(struct e1000_hw * hw)736*8044SWilliam.Kucharski@Sun.COM e1000_set_phy_type(struct e1000_hw *hw)
737*8044SWilliam.Kucharski@Sun.COM {
738*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_set_phy_type");
739*8044SWilliam.Kucharski@Sun.COM
740*8044SWilliam.Kucharski@Sun.COM switch(hw->phy_id) {
741*8044SWilliam.Kucharski@Sun.COM case M88E1000_E_PHY_ID:
742*8044SWilliam.Kucharski@Sun.COM case M88E1000_I_PHY_ID:
743*8044SWilliam.Kucharski@Sun.COM case M88E1011_I_PHY_ID:
744*8044SWilliam.Kucharski@Sun.COM hw->phy_type = e1000_phy_m88;
745*8044SWilliam.Kucharski@Sun.COM break;
746*8044SWilliam.Kucharski@Sun.COM case IGP01E1000_I_PHY_ID:
747*8044SWilliam.Kucharski@Sun.COM hw->phy_type = e1000_phy_igp;
748*8044SWilliam.Kucharski@Sun.COM break;
749*8044SWilliam.Kucharski@Sun.COM default:
750*8044SWilliam.Kucharski@Sun.COM /* Should never have loaded on this device */
751*8044SWilliam.Kucharski@Sun.COM hw->phy_type = e1000_phy_undefined;
752*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_PHY_TYPE;
753*8044SWilliam.Kucharski@Sun.COM }
754*8044SWilliam.Kucharski@Sun.COM
755*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
756*8044SWilliam.Kucharski@Sun.COM }
757*8044SWilliam.Kucharski@Sun.COM
758*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
759*8044SWilliam.Kucharski@Sun.COM * IGP phy init script - initializes the GbE PHY
760*8044SWilliam.Kucharski@Sun.COM *
761*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
762*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
763*8044SWilliam.Kucharski@Sun.COM static void
e1000_phy_init_script(struct e1000_hw * hw)764*8044SWilliam.Kucharski@Sun.COM e1000_phy_init_script(struct e1000_hw *hw)
765*8044SWilliam.Kucharski@Sun.COM {
766*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_phy_init_script");
767*8044SWilliam.Kucharski@Sun.COM
768*8044SWilliam.Kucharski@Sun.COM #if 0
769*8044SWilliam.Kucharski@Sun.COM /* See e1000_sw_init() of the Linux driver */
770*8044SWilliam.Kucharski@Sun.COM if(hw->phy_init_script) {
771*8044SWilliam.Kucharski@Sun.COM #else
772*8044SWilliam.Kucharski@Sun.COM if((hw->mac_type == e1000_82541) ||
773*8044SWilliam.Kucharski@Sun.COM (hw->mac_type == e1000_82547) ||
774*8044SWilliam.Kucharski@Sun.COM (hw->mac_type == e1000_82541_rev_2) ||
775*8044SWilliam.Kucharski@Sun.COM (hw->mac_type == e1000_82547_rev_2)) {
776*8044SWilliam.Kucharski@Sun.COM #endif
777*8044SWilliam.Kucharski@Sun.COM mdelay(20);
778*8044SWilliam.Kucharski@Sun.COM
779*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw,0x0000,0x0140);
780*8044SWilliam.Kucharski@Sun.COM
781*8044SWilliam.Kucharski@Sun.COM mdelay(5);
782*8044SWilliam.Kucharski@Sun.COM
783*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547) {
784*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F95, 0x0001);
785*8044SWilliam.Kucharski@Sun.COM
786*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
787*8044SWilliam.Kucharski@Sun.COM
788*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F79, 0x0018);
789*8044SWilliam.Kucharski@Sun.COM
790*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F30, 0x1600);
791*8044SWilliam.Kucharski@Sun.COM
792*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F31, 0x0014);
793*8044SWilliam.Kucharski@Sun.COM
794*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F32, 0x161C);
795*8044SWilliam.Kucharski@Sun.COM
796*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F94, 0x0003);
797*8044SWilliam.Kucharski@Sun.COM
798*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F96, 0x003F);
799*8044SWilliam.Kucharski@Sun.COM
800*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x2010, 0x0008);
801*8044SWilliam.Kucharski@Sun.COM } else {
802*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x1F73, 0x0099);
803*8044SWilliam.Kucharski@Sun.COM }
804*8044SWilliam.Kucharski@Sun.COM
805*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, 0x0000, 0x3300);
806*8044SWilliam.Kucharski@Sun.COM
807*8044SWilliam.Kucharski@Sun.COM
808*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82547) {
809*8044SWilliam.Kucharski@Sun.COM uint16_t fused, fine, coarse;
810*8044SWilliam.Kucharski@Sun.COM
811*8044SWilliam.Kucharski@Sun.COM /* Move to analog registers page */
812*8044SWilliam.Kucharski@Sun.COM e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
813*8044SWilliam.Kucharski@Sun.COM
814*8044SWilliam.Kucharski@Sun.COM if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
815*8044SWilliam.Kucharski@Sun.COM e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused);
816*8044SWilliam.Kucharski@Sun.COM
817*8044SWilliam.Kucharski@Sun.COM fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
818*8044SWilliam.Kucharski@Sun.COM coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
819*8044SWilliam.Kucharski@Sun.COM
820*8044SWilliam.Kucharski@Sun.COM if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
821*8044SWilliam.Kucharski@Sun.COM coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
822*8044SWilliam.Kucharski@Sun.COM fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
823*8044SWilliam.Kucharski@Sun.COM } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
824*8044SWilliam.Kucharski@Sun.COM fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
825*8044SWilliam.Kucharski@Sun.COM
826*8044SWilliam.Kucharski@Sun.COM fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
827*8044SWilliam.Kucharski@Sun.COM (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
828*8044SWilliam.Kucharski@Sun.COM (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
829*8044SWilliam.Kucharski@Sun.COM
830*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused);
831*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS,
832*8044SWilliam.Kucharski@Sun.COM IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
833*8044SWilliam.Kucharski@Sun.COM }
834*8044SWilliam.Kucharski@Sun.COM }
835*8044SWilliam.Kucharski@Sun.COM }
836*8044SWilliam.Kucharski@Sun.COM }
837*8044SWilliam.Kucharski@Sun.COM
838*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
839*8044SWilliam.Kucharski@Sun.COM * Set the mac type member in the hw struct.
840*8044SWilliam.Kucharski@Sun.COM *
841*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
842*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
843*8044SWilliam.Kucharski@Sun.COM static int
844*8044SWilliam.Kucharski@Sun.COM e1000_set_mac_type(struct e1000_hw *hw)
845*8044SWilliam.Kucharski@Sun.COM {
846*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_set_mac_type");
847*8044SWilliam.Kucharski@Sun.COM
848*8044SWilliam.Kucharski@Sun.COM switch (hw->device_id) {
849*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82542:
850*8044SWilliam.Kucharski@Sun.COM switch (hw->revision_id) {
851*8044SWilliam.Kucharski@Sun.COM case E1000_82542_2_0_REV_ID:
852*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82542_rev2_0;
853*8044SWilliam.Kucharski@Sun.COM break;
854*8044SWilliam.Kucharski@Sun.COM case E1000_82542_2_1_REV_ID:
855*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82542_rev2_1;
856*8044SWilliam.Kucharski@Sun.COM break;
857*8044SWilliam.Kucharski@Sun.COM default:
858*8044SWilliam.Kucharski@Sun.COM /* Invalid 82542 revision ID */
859*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_MAC_TYPE;
860*8044SWilliam.Kucharski@Sun.COM }
861*8044SWilliam.Kucharski@Sun.COM break;
862*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82543GC_FIBER:
863*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82543GC_COPPER:
864*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82543;
865*8044SWilliam.Kucharski@Sun.COM break;
866*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82544EI_COPPER:
867*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82544EI_FIBER:
868*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82544GC_COPPER:
869*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82544GC_LOM:
870*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82544;
871*8044SWilliam.Kucharski@Sun.COM break;
872*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82540EM:
873*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82540EM_LOM:
874*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82540EP:
875*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82540EP_LOM:
876*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82540EP_LP:
877*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82540;
878*8044SWilliam.Kucharski@Sun.COM break;
879*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82545EM_COPPER:
880*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82545EM_FIBER:
881*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82545;
882*8044SWilliam.Kucharski@Sun.COM break;
883*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82545GM_COPPER:
884*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82545GM_FIBER:
885*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82545GM_SERDES:
886*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82545_rev_3;
887*8044SWilliam.Kucharski@Sun.COM break;
888*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82546EB_COPPER:
889*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82546EB_FIBER:
890*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82546EB_QUAD_COPPER:
891*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82546;
892*8044SWilliam.Kucharski@Sun.COM break;
893*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82546GB_COPPER:
894*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82546GB_FIBER:
895*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82546GB_SERDES:
896*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82546_rev_3;
897*8044SWilliam.Kucharski@Sun.COM break;
898*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82541EI:
899*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82541EI_MOBILE:
900*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82541;
901*8044SWilliam.Kucharski@Sun.COM break;
902*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82541ER:
903*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82541GI:
904*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82541GI_MOBILE:
905*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82541_rev_2;
906*8044SWilliam.Kucharski@Sun.COM break;
907*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82547EI:
908*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82547;
909*8044SWilliam.Kucharski@Sun.COM break;
910*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82547GI:
911*8044SWilliam.Kucharski@Sun.COM hw->mac_type = e1000_82547_rev_2;
912*8044SWilliam.Kucharski@Sun.COM break;
913*8044SWilliam.Kucharski@Sun.COM default:
914*8044SWilliam.Kucharski@Sun.COM /* Should never have loaded on this device */
915*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_MAC_TYPE;
916*8044SWilliam.Kucharski@Sun.COM }
917*8044SWilliam.Kucharski@Sun.COM
918*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
919*8044SWilliam.Kucharski@Sun.COM }
920*8044SWilliam.Kucharski@Sun.COM
921*8044SWilliam.Kucharski@Sun.COM /*****************************************************************************
922*8044SWilliam.Kucharski@Sun.COM * Set media type and TBI compatibility.
923*8044SWilliam.Kucharski@Sun.COM *
924*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
925*8044SWilliam.Kucharski@Sun.COM * **************************************************************************/
926*8044SWilliam.Kucharski@Sun.COM static void
927*8044SWilliam.Kucharski@Sun.COM e1000_set_media_type(struct e1000_hw *hw)
928*8044SWilliam.Kucharski@Sun.COM {
929*8044SWilliam.Kucharski@Sun.COM uint32_t status;
930*8044SWilliam.Kucharski@Sun.COM
931*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_set_media_type");
932*8044SWilliam.Kucharski@Sun.COM
933*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type != e1000_82543) {
934*8044SWilliam.Kucharski@Sun.COM /* tbi_compatibility is only valid on 82543 */
935*8044SWilliam.Kucharski@Sun.COM hw->tbi_compatibility_en = FALSE;
936*8044SWilliam.Kucharski@Sun.COM }
937*8044SWilliam.Kucharski@Sun.COM
938*8044SWilliam.Kucharski@Sun.COM switch (hw->device_id) {
939*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82545GM_SERDES:
940*8044SWilliam.Kucharski@Sun.COM case E1000_DEV_ID_82546GB_SERDES:
941*8044SWilliam.Kucharski@Sun.COM hw->media_type = e1000_media_type_internal_serdes;
942*8044SWilliam.Kucharski@Sun.COM break;
943*8044SWilliam.Kucharski@Sun.COM default:
944*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type >= e1000_82543) {
945*8044SWilliam.Kucharski@Sun.COM status = E1000_READ_REG(hw, STATUS);
946*8044SWilliam.Kucharski@Sun.COM if(status & E1000_STATUS_TBIMODE) {
947*8044SWilliam.Kucharski@Sun.COM hw->media_type = e1000_media_type_fiber;
948*8044SWilliam.Kucharski@Sun.COM /* tbi_compatibility not valid on fiber */
949*8044SWilliam.Kucharski@Sun.COM hw->tbi_compatibility_en = FALSE;
950*8044SWilliam.Kucharski@Sun.COM } else {
951*8044SWilliam.Kucharski@Sun.COM hw->media_type = e1000_media_type_copper;
952*8044SWilliam.Kucharski@Sun.COM }
953*8044SWilliam.Kucharski@Sun.COM } else {
954*8044SWilliam.Kucharski@Sun.COM /* This is an 82542 (fiber only) */
955*8044SWilliam.Kucharski@Sun.COM hw->media_type = e1000_media_type_fiber;
956*8044SWilliam.Kucharski@Sun.COM }
957*8044SWilliam.Kucharski@Sun.COM }
958*8044SWilliam.Kucharski@Sun.COM }
959*8044SWilliam.Kucharski@Sun.COM
960*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
961*8044SWilliam.Kucharski@Sun.COM * Reset the transmit and receive units; mask and clear all interrupts.
962*8044SWilliam.Kucharski@Sun.COM *
963*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
964*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
965*8044SWilliam.Kucharski@Sun.COM static void
966*8044SWilliam.Kucharski@Sun.COM e1000_reset_hw(struct e1000_hw *hw)
967*8044SWilliam.Kucharski@Sun.COM {
968*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl;
969*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl_ext;
970*8044SWilliam.Kucharski@Sun.COM uint32_t icr;
971*8044SWilliam.Kucharski@Sun.COM uint32_t manc;
972*8044SWilliam.Kucharski@Sun.COM
973*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_reset_hw");
974*8044SWilliam.Kucharski@Sun.COM
975*8044SWilliam.Kucharski@Sun.COM /* For 82542 (rev 2.0), disable MWI before issuing a device reset */
976*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82542_rev2_0) {
977*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
978*8044SWilliam.Kucharski@Sun.COM e1000_pci_clear_mwi(hw);
979*8044SWilliam.Kucharski@Sun.COM }
980*8044SWilliam.Kucharski@Sun.COM
981*8044SWilliam.Kucharski@Sun.COM /* Clear interrupt mask to stop board from generating interrupts */
982*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Masking off all interrupts\n");
983*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, IMC, 0xffffffff);
984*8044SWilliam.Kucharski@Sun.COM
985*8044SWilliam.Kucharski@Sun.COM /* Disable the Transmit and Receive units. Then delay to allow
986*8044SWilliam.Kucharski@Sun.COM * any pending transactions to complete before we hit the MAC with
987*8044SWilliam.Kucharski@Sun.COM * the global reset.
988*8044SWilliam.Kucharski@Sun.COM */
989*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, RCTL, 0);
990*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP);
991*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
992*8044SWilliam.Kucharski@Sun.COM
993*8044SWilliam.Kucharski@Sun.COM /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
994*8044SWilliam.Kucharski@Sun.COM hw->tbi_compatibility_on = FALSE;
995*8044SWilliam.Kucharski@Sun.COM
996*8044SWilliam.Kucharski@Sun.COM /* Delay to allow any outstanding PCI transactions to complete before
997*8044SWilliam.Kucharski@Sun.COM * resetting the device
998*8044SWilliam.Kucharski@Sun.COM */
999*8044SWilliam.Kucharski@Sun.COM mdelay(10);
1000*8044SWilliam.Kucharski@Sun.COM
1001*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
1002*8044SWilliam.Kucharski@Sun.COM
1003*8044SWilliam.Kucharski@Sun.COM /* Must reset the PHY before resetting the MAC */
1004*8044SWilliam.Kucharski@Sun.COM if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
1005*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
1006*8044SWilliam.Kucharski@Sun.COM mdelay(5);
1007*8044SWilliam.Kucharski@Sun.COM }
1008*8044SWilliam.Kucharski@Sun.COM
1009*8044SWilliam.Kucharski@Sun.COM /* Issue a global reset to the MAC. This will reset the chip's
1010*8044SWilliam.Kucharski@Sun.COM * transmit, receive, DMA, and link units. It will not effect
1011*8044SWilliam.Kucharski@Sun.COM * the current PCI configuration. The global reset bit is self-
1012*8044SWilliam.Kucharski@Sun.COM * clearing, and should clear within a microsecond.
1013*8044SWilliam.Kucharski@Sun.COM */
1014*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Issuing a global reset to MAC\n");
1015*8044SWilliam.Kucharski@Sun.COM
1016*8044SWilliam.Kucharski@Sun.COM switch(hw->mac_type) {
1017*8044SWilliam.Kucharski@Sun.COM case e1000_82544:
1018*8044SWilliam.Kucharski@Sun.COM case e1000_82540:
1019*8044SWilliam.Kucharski@Sun.COM case e1000_82545:
1020*8044SWilliam.Kucharski@Sun.COM case e1000_82546:
1021*8044SWilliam.Kucharski@Sun.COM case e1000_82541:
1022*8044SWilliam.Kucharski@Sun.COM case e1000_82541_rev_2:
1023*8044SWilliam.Kucharski@Sun.COM /* These controllers can't ack the 64-bit write when issuing the
1024*8044SWilliam.Kucharski@Sun.COM * reset, so use IO-mapping as a workaround to issue the reset */
1025*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
1026*8044SWilliam.Kucharski@Sun.COM break;
1027*8044SWilliam.Kucharski@Sun.COM case e1000_82545_rev_3:
1028*8044SWilliam.Kucharski@Sun.COM case e1000_82546_rev_3:
1029*8044SWilliam.Kucharski@Sun.COM /* Reset is performed on a shadow of the control register */
1030*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST));
1031*8044SWilliam.Kucharski@Sun.COM break;
1032*8044SWilliam.Kucharski@Sun.COM default:
1033*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
1034*8044SWilliam.Kucharski@Sun.COM break;
1035*8044SWilliam.Kucharski@Sun.COM }
1036*8044SWilliam.Kucharski@Sun.COM
1037*8044SWilliam.Kucharski@Sun.COM /* After MAC reset, force reload of EEPROM to restore power-on settings to
1038*8044SWilliam.Kucharski@Sun.COM * device. Later controllers reload the EEPROM automatically, so just wait
1039*8044SWilliam.Kucharski@Sun.COM * for reload to complete.
1040*8044SWilliam.Kucharski@Sun.COM */
1041*8044SWilliam.Kucharski@Sun.COM switch(hw->mac_type) {
1042*8044SWilliam.Kucharski@Sun.COM case e1000_82542_rev2_0:
1043*8044SWilliam.Kucharski@Sun.COM case e1000_82542_rev2_1:
1044*8044SWilliam.Kucharski@Sun.COM case e1000_82543:
1045*8044SWilliam.Kucharski@Sun.COM case e1000_82544:
1046*8044SWilliam.Kucharski@Sun.COM /* Wait for reset to complete */
1047*8044SWilliam.Kucharski@Sun.COM udelay(10);
1048*8044SWilliam.Kucharski@Sun.COM ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
1049*8044SWilliam.Kucharski@Sun.COM ctrl_ext |= E1000_CTRL_EXT_EE_RST;
1050*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
1051*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
1052*8044SWilliam.Kucharski@Sun.COM /* Wait for EEPROM reload */
1053*8044SWilliam.Kucharski@Sun.COM mdelay(2);
1054*8044SWilliam.Kucharski@Sun.COM break;
1055*8044SWilliam.Kucharski@Sun.COM case e1000_82541:
1056*8044SWilliam.Kucharski@Sun.COM case e1000_82541_rev_2:
1057*8044SWilliam.Kucharski@Sun.COM case e1000_82547:
1058*8044SWilliam.Kucharski@Sun.COM case e1000_82547_rev_2:
1059*8044SWilliam.Kucharski@Sun.COM /* Wait for EEPROM reload */
1060*8044SWilliam.Kucharski@Sun.COM mdelay(20);
1061*8044SWilliam.Kucharski@Sun.COM break;
1062*8044SWilliam.Kucharski@Sun.COM default:
1063*8044SWilliam.Kucharski@Sun.COM /* Wait for EEPROM reload (it happens automatically) */
1064*8044SWilliam.Kucharski@Sun.COM mdelay(5);
1065*8044SWilliam.Kucharski@Sun.COM break;
1066*8044SWilliam.Kucharski@Sun.COM }
1067*8044SWilliam.Kucharski@Sun.COM
1068*8044SWilliam.Kucharski@Sun.COM /* Disable HW ARPs on ASF enabled adapters */
1069*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type >= e1000_82540) {
1070*8044SWilliam.Kucharski@Sun.COM manc = E1000_READ_REG(hw, MANC);
1071*8044SWilliam.Kucharski@Sun.COM manc &= ~(E1000_MANC_ARP_EN);
1072*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, MANC, manc);
1073*8044SWilliam.Kucharski@Sun.COM }
1074*8044SWilliam.Kucharski@Sun.COM
1075*8044SWilliam.Kucharski@Sun.COM if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
1076*8044SWilliam.Kucharski@Sun.COM e1000_phy_init_script(hw);
1077*8044SWilliam.Kucharski@Sun.COM }
1078*8044SWilliam.Kucharski@Sun.COM
1079*8044SWilliam.Kucharski@Sun.COM /* Clear interrupt mask to stop board from generating interrupts */
1080*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Masking off all interrupts\n");
1081*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, IMC, 0xffffffff);
1082*8044SWilliam.Kucharski@Sun.COM
1083*8044SWilliam.Kucharski@Sun.COM /* Clear any pending interrupt events. */
1084*8044SWilliam.Kucharski@Sun.COM icr = E1000_READ_REG(hw, ICR);
1085*8044SWilliam.Kucharski@Sun.COM
1086*8044SWilliam.Kucharski@Sun.COM /* If MWI was previously enabled, reenable it. */
1087*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82542_rev2_0) {
1088*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
1089*8044SWilliam.Kucharski@Sun.COM if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
1090*8044SWilliam.Kucharski@Sun.COM #endif
1091*8044SWilliam.Kucharski@Sun.COM e1000_pci_set_mwi(hw);
1092*8044SWilliam.Kucharski@Sun.COM }
1093*8044SWilliam.Kucharski@Sun.COM }
1094*8044SWilliam.Kucharski@Sun.COM
1095*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1096*8044SWilliam.Kucharski@Sun.COM * Performs basic configuration of the adapter.
1097*8044SWilliam.Kucharski@Sun.COM *
1098*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
1099*8044SWilliam.Kucharski@Sun.COM *
1100*8044SWilliam.Kucharski@Sun.COM * Assumes that the controller has previously been reset and is in a
1101*8044SWilliam.Kucharski@Sun.COM * post-reset uninitialized state. Initializes the receive address registers,
1102*8044SWilliam.Kucharski@Sun.COM * multicast table, and VLAN filter table. Calls routines to setup link
1103*8044SWilliam.Kucharski@Sun.COM * configuration and flow control settings. Clears all on-chip counters. Leaves
1104*8044SWilliam.Kucharski@Sun.COM * the transmit and receive units disabled and uninitialized.
1105*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
1106*8044SWilliam.Kucharski@Sun.COM static int
1107*8044SWilliam.Kucharski@Sun.COM e1000_init_hw(struct e1000_hw *hw)
1108*8044SWilliam.Kucharski@Sun.COM {
1109*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl, status;
1110*8044SWilliam.Kucharski@Sun.COM uint32_t i;
1111*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
1112*8044SWilliam.Kucharski@Sun.COM uint16_t pcix_cmd_word;
1113*8044SWilliam.Kucharski@Sun.COM uint16_t pcix_stat_hi_word;
1114*8044SWilliam.Kucharski@Sun.COM uint16_t cmd_mmrbc;
1115*8044SWilliam.Kucharski@Sun.COM uint16_t stat_mmrbc;
1116*8044SWilliam.Kucharski@Sun.COM e1000_bus_type bus_type = e1000_bus_type_unknown;
1117*8044SWilliam.Kucharski@Sun.COM
1118*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_init_hw");
1119*8044SWilliam.Kucharski@Sun.COM
1120*8044SWilliam.Kucharski@Sun.COM /* Set the media type and TBI compatibility */
1121*8044SWilliam.Kucharski@Sun.COM e1000_set_media_type(hw);
1122*8044SWilliam.Kucharski@Sun.COM
1123*8044SWilliam.Kucharski@Sun.COM /* Disabling VLAN filtering. */
1124*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Initializing the IEEE VLAN\n");
1125*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, VET, 0);
1126*8044SWilliam.Kucharski@Sun.COM
1127*8044SWilliam.Kucharski@Sun.COM e1000_clear_vfta(hw);
1128*8044SWilliam.Kucharski@Sun.COM
1129*8044SWilliam.Kucharski@Sun.COM /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
1130*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82542_rev2_0) {
1131*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
1132*8044SWilliam.Kucharski@Sun.COM e1000_pci_clear_mwi(hw);
1133*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
1134*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
1135*8044SWilliam.Kucharski@Sun.COM mdelay(5);
1136*8044SWilliam.Kucharski@Sun.COM }
1137*8044SWilliam.Kucharski@Sun.COM
1138*8044SWilliam.Kucharski@Sun.COM /* Setup the receive address. This involves initializing all of the Receive
1139*8044SWilliam.Kucharski@Sun.COM * Address Registers (RARs 0 - 15).
1140*8044SWilliam.Kucharski@Sun.COM */
1141*8044SWilliam.Kucharski@Sun.COM e1000_init_rx_addrs(hw);
1142*8044SWilliam.Kucharski@Sun.COM
1143*8044SWilliam.Kucharski@Sun.COM /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
1144*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82542_rev2_0) {
1145*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, RCTL, 0);
1146*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
1147*8044SWilliam.Kucharski@Sun.COM mdelay(1);
1148*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
1149*8044SWilliam.Kucharski@Sun.COM if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
1150*8044SWilliam.Kucharski@Sun.COM #endif
1151*8044SWilliam.Kucharski@Sun.COM e1000_pci_set_mwi(hw);
1152*8044SWilliam.Kucharski@Sun.COM }
1153*8044SWilliam.Kucharski@Sun.COM
1154*8044SWilliam.Kucharski@Sun.COM /* Zero out the Multicast HASH table */
1155*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Zeroing the MTA\n");
1156*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < E1000_MC_TBL_SIZE; i++)
1157*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
1158*8044SWilliam.Kucharski@Sun.COM
1159*8044SWilliam.Kucharski@Sun.COM #if 0
1160*8044SWilliam.Kucharski@Sun.COM /* Set the PCI priority bit correctly in the CTRL register. This
1161*8044SWilliam.Kucharski@Sun.COM * determines if the adapter gives priority to receives, or if it
1162*8044SWilliam.Kucharski@Sun.COM * gives equal priority to transmits and receives.
1163*8044SWilliam.Kucharski@Sun.COM */
1164*8044SWilliam.Kucharski@Sun.COM if(hw->dma_fairness) {
1165*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
1166*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
1167*8044SWilliam.Kucharski@Sun.COM }
1168*8044SWilliam.Kucharski@Sun.COM #endif
1169*8044SWilliam.Kucharski@Sun.COM
1170*8044SWilliam.Kucharski@Sun.COM switch(hw->mac_type) {
1171*8044SWilliam.Kucharski@Sun.COM case e1000_82545_rev_3:
1172*8044SWilliam.Kucharski@Sun.COM case e1000_82546_rev_3:
1173*8044SWilliam.Kucharski@Sun.COM break;
1174*8044SWilliam.Kucharski@Sun.COM default:
1175*8044SWilliam.Kucharski@Sun.COM if (hw->mac_type >= e1000_82543) {
1176*8044SWilliam.Kucharski@Sun.COM /* See e1000_get_bus_info() of the Linux driver */
1177*8044SWilliam.Kucharski@Sun.COM status = E1000_READ_REG(hw, STATUS);
1178*8044SWilliam.Kucharski@Sun.COM bus_type = (status & E1000_STATUS_PCIX_MODE) ?
1179*8044SWilliam.Kucharski@Sun.COM e1000_bus_type_pcix : e1000_bus_type_pci;
1180*8044SWilliam.Kucharski@Sun.COM }
1181*8044SWilliam.Kucharski@Sun.COM
1182*8044SWilliam.Kucharski@Sun.COM /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
1183*8044SWilliam.Kucharski@Sun.COM if(bus_type == e1000_bus_type_pcix) {
1184*8044SWilliam.Kucharski@Sun.COM pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER, &pcix_cmd_word);
1185*8044SWilliam.Kucharski@Sun.COM pci_read_config_word(hw->pdev, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word);
1186*8044SWilliam.Kucharski@Sun.COM cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >>
1187*8044SWilliam.Kucharski@Sun.COM PCIX_COMMAND_MMRBC_SHIFT;
1188*8044SWilliam.Kucharski@Sun.COM stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
1189*8044SWilliam.Kucharski@Sun.COM PCIX_STATUS_HI_MMRBC_SHIFT;
1190*8044SWilliam.Kucharski@Sun.COM if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
1191*8044SWilliam.Kucharski@Sun.COM stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
1192*8044SWilliam.Kucharski@Sun.COM if(cmd_mmrbc > stat_mmrbc) {
1193*8044SWilliam.Kucharski@Sun.COM pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK;
1194*8044SWilliam.Kucharski@Sun.COM pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
1195*8044SWilliam.Kucharski@Sun.COM pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER, pcix_cmd_word);
1196*8044SWilliam.Kucharski@Sun.COM }
1197*8044SWilliam.Kucharski@Sun.COM }
1198*8044SWilliam.Kucharski@Sun.COM break;
1199*8044SWilliam.Kucharski@Sun.COM }
1200*8044SWilliam.Kucharski@Sun.COM
1201*8044SWilliam.Kucharski@Sun.COM /* Call a subroutine to configure the link and setup flow control. */
1202*8044SWilliam.Kucharski@Sun.COM ret_val = e1000_setup_link(hw);
1203*8044SWilliam.Kucharski@Sun.COM
1204*8044SWilliam.Kucharski@Sun.COM /* Set the transmit descriptor write-back policy */
1205*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type > e1000_82544) {
1206*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, TXDCTL);
1207*8044SWilliam.Kucharski@Sun.COM ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
1208*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, TXDCTL, ctrl);
1209*8044SWilliam.Kucharski@Sun.COM }
1210*8044SWilliam.Kucharski@Sun.COM
1211*8044SWilliam.Kucharski@Sun.COM #if 0
1212*8044SWilliam.Kucharski@Sun.COM /* Clear all of the statistics registers (clear on read). It is
1213*8044SWilliam.Kucharski@Sun.COM * important that we do this after we have tried to establish link
1214*8044SWilliam.Kucharski@Sun.COM * because the symbol error count will increment wildly if there
1215*8044SWilliam.Kucharski@Sun.COM * is no link.
1216*8044SWilliam.Kucharski@Sun.COM */
1217*8044SWilliam.Kucharski@Sun.COM e1000_clear_hw_cntrs(hw);
1218*8044SWilliam.Kucharski@Sun.COM #endif
1219*8044SWilliam.Kucharski@Sun.COM
1220*8044SWilliam.Kucharski@Sun.COM return ret_val;
1221*8044SWilliam.Kucharski@Sun.COM }
1222*8044SWilliam.Kucharski@Sun.COM
1223*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1224*8044SWilliam.Kucharski@Sun.COM * Adjust SERDES output amplitude based on EEPROM setting.
1225*8044SWilliam.Kucharski@Sun.COM *
1226*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code.
1227*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
1228*8044SWilliam.Kucharski@Sun.COM static int32_t
1229*8044SWilliam.Kucharski@Sun.COM e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
1230*8044SWilliam.Kucharski@Sun.COM {
1231*8044SWilliam.Kucharski@Sun.COM uint16_t eeprom_data;
1232*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
1233*8044SWilliam.Kucharski@Sun.COM
1234*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_adjust_serdes_amplitude");
1235*8044SWilliam.Kucharski@Sun.COM
1236*8044SWilliam.Kucharski@Sun.COM if(hw->media_type != e1000_media_type_internal_serdes)
1237*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
1238*8044SWilliam.Kucharski@Sun.COM
1239*8044SWilliam.Kucharski@Sun.COM switch(hw->mac_type) {
1240*8044SWilliam.Kucharski@Sun.COM case e1000_82545_rev_3:
1241*8044SWilliam.Kucharski@Sun.COM case e1000_82546_rev_3:
1242*8044SWilliam.Kucharski@Sun.COM break;
1243*8044SWilliam.Kucharski@Sun.COM default:
1244*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
1245*8044SWilliam.Kucharski@Sun.COM }
1246*8044SWilliam.Kucharski@Sun.COM
1247*8044SWilliam.Kucharski@Sun.COM if ((ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1,
1248*8044SWilliam.Kucharski@Sun.COM &eeprom_data))) {
1249*8044SWilliam.Kucharski@Sun.COM return ret_val;
1250*8044SWilliam.Kucharski@Sun.COM }
1251*8044SWilliam.Kucharski@Sun.COM
1252*8044SWilliam.Kucharski@Sun.COM if(eeprom_data != EEPROM_RESERVED_WORD) {
1253*8044SWilliam.Kucharski@Sun.COM /* Adjust SERDES output amplitude only. */
1254*8044SWilliam.Kucharski@Sun.COM eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
1255*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL,
1256*8044SWilliam.Kucharski@Sun.COM eeprom_data)))
1257*8044SWilliam.Kucharski@Sun.COM return ret_val;
1258*8044SWilliam.Kucharski@Sun.COM }
1259*8044SWilliam.Kucharski@Sun.COM
1260*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
1261*8044SWilliam.Kucharski@Sun.COM }
1262*8044SWilliam.Kucharski@Sun.COM
1263*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1264*8044SWilliam.Kucharski@Sun.COM * Configures flow control and link settings.
1265*8044SWilliam.Kucharski@Sun.COM *
1266*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
1267*8044SWilliam.Kucharski@Sun.COM *
1268*8044SWilliam.Kucharski@Sun.COM * Determines which flow control settings to use. Calls the apropriate media-
1269*8044SWilliam.Kucharski@Sun.COM * specific link configuration function. Configures the flow control settings.
1270*8044SWilliam.Kucharski@Sun.COM * Assuming the adapter has a valid link partner, a valid link should be
1271*8044SWilliam.Kucharski@Sun.COM * established. Assumes the hardware has previously been reset and the
1272*8044SWilliam.Kucharski@Sun.COM * transmitter and receiver are not enabled.
1273*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
1274*8044SWilliam.Kucharski@Sun.COM static int
1275*8044SWilliam.Kucharski@Sun.COM e1000_setup_link(struct e1000_hw *hw)
1276*8044SWilliam.Kucharski@Sun.COM {
1277*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl_ext;
1278*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
1279*8044SWilliam.Kucharski@Sun.COM uint16_t eeprom_data;
1280*8044SWilliam.Kucharski@Sun.COM
1281*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_setup_link");
1282*8044SWilliam.Kucharski@Sun.COM
1283*8044SWilliam.Kucharski@Sun.COM /* Read and store word 0x0F of the EEPROM. This word contains bits
1284*8044SWilliam.Kucharski@Sun.COM * that determine the hardware's default PAUSE (flow control) mode,
1285*8044SWilliam.Kucharski@Sun.COM * a bit that determines whether the HW defaults to enabling or
1286*8044SWilliam.Kucharski@Sun.COM * disabling auto-negotiation, and the direction of the
1287*8044SWilliam.Kucharski@Sun.COM * SW defined pins. If there is no SW over-ride of the flow
1288*8044SWilliam.Kucharski@Sun.COM * control setting, then the variable hw->fc will
1289*8044SWilliam.Kucharski@Sun.COM * be initialized based on a value in the EEPROM.
1290*8044SWilliam.Kucharski@Sun.COM */
1291*8044SWilliam.Kucharski@Sun.COM if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) {
1292*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("EEPROM Read Error\n");
1293*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_EEPROM;
1294*8044SWilliam.Kucharski@Sun.COM }
1295*8044SWilliam.Kucharski@Sun.COM
1296*8044SWilliam.Kucharski@Sun.COM if(hw->fc == e1000_fc_default) {
1297*8044SWilliam.Kucharski@Sun.COM if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
1298*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_none;
1299*8044SWilliam.Kucharski@Sun.COM else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
1300*8044SWilliam.Kucharski@Sun.COM EEPROM_WORD0F_ASM_DIR)
1301*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_tx_pause;
1302*8044SWilliam.Kucharski@Sun.COM else
1303*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_full;
1304*8044SWilliam.Kucharski@Sun.COM }
1305*8044SWilliam.Kucharski@Sun.COM
1306*8044SWilliam.Kucharski@Sun.COM /* We want to save off the original Flow Control configuration just
1307*8044SWilliam.Kucharski@Sun.COM * in case we get disconnected and then reconnected into a different
1308*8044SWilliam.Kucharski@Sun.COM * hub or switch with different Flow Control capabilities.
1309*8044SWilliam.Kucharski@Sun.COM */
1310*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82542_rev2_0)
1311*8044SWilliam.Kucharski@Sun.COM hw->fc &= (~e1000_fc_tx_pause);
1312*8044SWilliam.Kucharski@Sun.COM
1313*8044SWilliam.Kucharski@Sun.COM #if 0
1314*8044SWilliam.Kucharski@Sun.COM /* See e1000_sw_init() of the Linux driver */
1315*8044SWilliam.Kucharski@Sun.COM if((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
1316*8044SWilliam.Kucharski@Sun.COM #else
1317*8044SWilliam.Kucharski@Sun.COM if((hw->mac_type < e1000_82543) && (hw->mac_type >= e1000_82543))
1318*8044SWilliam.Kucharski@Sun.COM #endif
1319*8044SWilliam.Kucharski@Sun.COM hw->fc &= (~e1000_fc_rx_pause);
1320*8044SWilliam.Kucharski@Sun.COM
1321*8044SWilliam.Kucharski@Sun.COM #if 0
1322*8044SWilliam.Kucharski@Sun.COM hw->original_fc = hw->fc;
1323*8044SWilliam.Kucharski@Sun.COM #endif
1324*8044SWilliam.Kucharski@Sun.COM
1325*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc);
1326*8044SWilliam.Kucharski@Sun.COM
1327*8044SWilliam.Kucharski@Sun.COM /* Take the 4 bits from EEPROM word 0x0F that determine the initial
1328*8044SWilliam.Kucharski@Sun.COM * polarity value for the SW controlled pins, and setup the
1329*8044SWilliam.Kucharski@Sun.COM * Extended Device Control reg with that info.
1330*8044SWilliam.Kucharski@Sun.COM * This is needed because one of the SW controlled pins is used for
1331*8044SWilliam.Kucharski@Sun.COM * signal detection. So this should be done before e1000_setup_pcs_link()
1332*8044SWilliam.Kucharski@Sun.COM * or e1000_phy_setup() is called.
1333*8044SWilliam.Kucharski@Sun.COM */
1334*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82543) {
1335*8044SWilliam.Kucharski@Sun.COM ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
1336*8044SWilliam.Kucharski@Sun.COM SWDPIO__EXT_SHIFT);
1337*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
1338*8044SWilliam.Kucharski@Sun.COM }
1339*8044SWilliam.Kucharski@Sun.COM
1340*8044SWilliam.Kucharski@Sun.COM /* Call the necessary subroutine to configure the link. */
1341*8044SWilliam.Kucharski@Sun.COM ret_val = (hw->media_type == e1000_media_type_copper) ?
1342*8044SWilliam.Kucharski@Sun.COM e1000_setup_copper_link(hw) :
1343*8044SWilliam.Kucharski@Sun.COM e1000_setup_fiber_serdes_link(hw);
1344*8044SWilliam.Kucharski@Sun.COM if (ret_val < 0) {
1345*8044SWilliam.Kucharski@Sun.COM return ret_val;
1346*8044SWilliam.Kucharski@Sun.COM }
1347*8044SWilliam.Kucharski@Sun.COM
1348*8044SWilliam.Kucharski@Sun.COM /* Initialize the flow control address, type, and PAUSE timer
1349*8044SWilliam.Kucharski@Sun.COM * registers to their default values. This is done even if flow
1350*8044SWilliam.Kucharski@Sun.COM * control is disabled, because it does not hurt anything to
1351*8044SWilliam.Kucharski@Sun.COM * initialize these registers.
1352*8044SWilliam.Kucharski@Sun.COM */
1353*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");
1354*8044SWilliam.Kucharski@Sun.COM
1355*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
1356*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
1357*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
1358*8044SWilliam.Kucharski@Sun.COM #if 0
1359*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
1360*8044SWilliam.Kucharski@Sun.COM #else
1361*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCTTV, FC_DEFAULT_TX_TIMER);
1362*8044SWilliam.Kucharski@Sun.COM #endif
1363*8044SWilliam.Kucharski@Sun.COM
1364*8044SWilliam.Kucharski@Sun.COM /* Set the flow control receive threshold registers. Normally,
1365*8044SWilliam.Kucharski@Sun.COM * these registers will be set to a default threshold that may be
1366*8044SWilliam.Kucharski@Sun.COM * adjusted later by the driver's runtime code. However, if the
1367*8044SWilliam.Kucharski@Sun.COM * ability to transmit pause frames in not enabled, then these
1368*8044SWilliam.Kucharski@Sun.COM * registers will be set to 0.
1369*8044SWilliam.Kucharski@Sun.COM */
1370*8044SWilliam.Kucharski@Sun.COM if(!(hw->fc & e1000_fc_tx_pause)) {
1371*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCRTL, 0);
1372*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCRTH, 0);
1373*8044SWilliam.Kucharski@Sun.COM } else {
1374*8044SWilliam.Kucharski@Sun.COM /* We need to set up the Receive Threshold high and low water marks
1375*8044SWilliam.Kucharski@Sun.COM * as well as (optionally) enabling the transmission of XON frames.
1376*8044SWilliam.Kucharski@Sun.COM */
1377*8044SWilliam.Kucharski@Sun.COM #if 0
1378*8044SWilliam.Kucharski@Sun.COM if(hw->fc_send_xon) {
1379*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
1380*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
1381*8044SWilliam.Kucharski@Sun.COM } else {
1382*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water);
1383*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
1384*8044SWilliam.Kucharski@Sun.COM }
1385*8044SWilliam.Kucharski@Sun.COM #else
1386*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCRTL, (FC_DEFAULT_LO_THRESH | E1000_FCRTL_XONE));
1387*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, FCRTH, FC_DEFAULT_HI_THRESH);
1388*8044SWilliam.Kucharski@Sun.COM #endif
1389*8044SWilliam.Kucharski@Sun.COM }
1390*8044SWilliam.Kucharski@Sun.COM return ret_val;
1391*8044SWilliam.Kucharski@Sun.COM }
1392*8044SWilliam.Kucharski@Sun.COM
1393*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1394*8044SWilliam.Kucharski@Sun.COM * Sets up link for a fiber based or serdes based adapter
1395*8044SWilliam.Kucharski@Sun.COM *
1396*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
1397*8044SWilliam.Kucharski@Sun.COM *
1398*8044SWilliam.Kucharski@Sun.COM * Manipulates Physical Coding Sublayer functions in order to configure
1399*8044SWilliam.Kucharski@Sun.COM * link. Assumes the hardware has been previously reset and the transmitter
1400*8044SWilliam.Kucharski@Sun.COM * and receiver are not enabled.
1401*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
1402*8044SWilliam.Kucharski@Sun.COM static int
1403*8044SWilliam.Kucharski@Sun.COM e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
1404*8044SWilliam.Kucharski@Sun.COM {
1405*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl;
1406*8044SWilliam.Kucharski@Sun.COM uint32_t status;
1407*8044SWilliam.Kucharski@Sun.COM uint32_t txcw = 0;
1408*8044SWilliam.Kucharski@Sun.COM uint32_t i;
1409*8044SWilliam.Kucharski@Sun.COM uint32_t signal = 0;
1410*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
1411*8044SWilliam.Kucharski@Sun.COM
1412*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_setup_fiber_serdes_link");
1413*8044SWilliam.Kucharski@Sun.COM
1414*8044SWilliam.Kucharski@Sun.COM /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
1415*8044SWilliam.Kucharski@Sun.COM * set when the optics detect a signal. On older adapters, it will be
1416*8044SWilliam.Kucharski@Sun.COM * cleared when there is a signal. This applies to fiber media only.
1417*8044SWilliam.Kucharski@Sun.COM * If we're on serdes media, adjust the output amplitude to value set in
1418*8044SWilliam.Kucharski@Sun.COM * the EEPROM.
1419*8044SWilliam.Kucharski@Sun.COM */
1420*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
1421*8044SWilliam.Kucharski@Sun.COM if(hw->media_type == e1000_media_type_fiber)
1422*8044SWilliam.Kucharski@Sun.COM signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
1423*8044SWilliam.Kucharski@Sun.COM
1424*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_adjust_serdes_amplitude(hw)))
1425*8044SWilliam.Kucharski@Sun.COM return ret_val;
1426*8044SWilliam.Kucharski@Sun.COM
1427*8044SWilliam.Kucharski@Sun.COM /* Take the link out of reset */
1428*8044SWilliam.Kucharski@Sun.COM ctrl &= ~(E1000_CTRL_LRST);
1429*8044SWilliam.Kucharski@Sun.COM
1430*8044SWilliam.Kucharski@Sun.COM #if 0
1431*8044SWilliam.Kucharski@Sun.COM /* Adjust VCO speed to improve BER performance */
1432*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_set_vco_speed(hw)))
1433*8044SWilliam.Kucharski@Sun.COM return ret_val;
1434*8044SWilliam.Kucharski@Sun.COM #endif
1435*8044SWilliam.Kucharski@Sun.COM
1436*8044SWilliam.Kucharski@Sun.COM e1000_config_collision_dist(hw);
1437*8044SWilliam.Kucharski@Sun.COM
1438*8044SWilliam.Kucharski@Sun.COM /* Check for a software override of the flow control settings, and setup
1439*8044SWilliam.Kucharski@Sun.COM * the device accordingly. If auto-negotiation is enabled, then software
1440*8044SWilliam.Kucharski@Sun.COM * will have to set the "PAUSE" bits to the correct value in the Tranmsit
1441*8044SWilliam.Kucharski@Sun.COM * Config Word Register (TXCW) and re-start auto-negotiation. However, if
1442*8044SWilliam.Kucharski@Sun.COM * auto-negotiation is disabled, then software will have to manually
1443*8044SWilliam.Kucharski@Sun.COM * configure the two flow control enable bits in the CTRL register.
1444*8044SWilliam.Kucharski@Sun.COM *
1445*8044SWilliam.Kucharski@Sun.COM * The possible values of the "fc" parameter are:
1446*8044SWilliam.Kucharski@Sun.COM * 0: Flow control is completely disabled
1447*8044SWilliam.Kucharski@Sun.COM * 1: Rx flow control is enabled (we can receive pause frames, but
1448*8044SWilliam.Kucharski@Sun.COM * not send pause frames).
1449*8044SWilliam.Kucharski@Sun.COM * 2: Tx flow control is enabled (we can send pause frames but we do
1450*8044SWilliam.Kucharski@Sun.COM * not support receiving pause frames).
1451*8044SWilliam.Kucharski@Sun.COM * 3: Both Rx and TX flow control (symmetric) are enabled.
1452*8044SWilliam.Kucharski@Sun.COM */
1453*8044SWilliam.Kucharski@Sun.COM switch (hw->fc) {
1454*8044SWilliam.Kucharski@Sun.COM case e1000_fc_none:
1455*8044SWilliam.Kucharski@Sun.COM /* Flow control is completely disabled by a software over-ride. */
1456*8044SWilliam.Kucharski@Sun.COM txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
1457*8044SWilliam.Kucharski@Sun.COM break;
1458*8044SWilliam.Kucharski@Sun.COM case e1000_fc_rx_pause:
1459*8044SWilliam.Kucharski@Sun.COM /* RX Flow control is enabled and TX Flow control is disabled by a
1460*8044SWilliam.Kucharski@Sun.COM * software over-ride. Since there really isn't a way to advertise
1461*8044SWilliam.Kucharski@Sun.COM * that we are capable of RX Pause ONLY, we will advertise that we
1462*8044SWilliam.Kucharski@Sun.COM * support both symmetric and asymmetric RX PAUSE. Later, we will
1463*8044SWilliam.Kucharski@Sun.COM * disable the adapter's ability to send PAUSE frames.
1464*8044SWilliam.Kucharski@Sun.COM */
1465*8044SWilliam.Kucharski@Sun.COM txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
1466*8044SWilliam.Kucharski@Sun.COM break;
1467*8044SWilliam.Kucharski@Sun.COM case e1000_fc_tx_pause:
1468*8044SWilliam.Kucharski@Sun.COM /* TX Flow control is enabled, and RX Flow control is disabled, by a
1469*8044SWilliam.Kucharski@Sun.COM * software over-ride.
1470*8044SWilliam.Kucharski@Sun.COM */
1471*8044SWilliam.Kucharski@Sun.COM txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
1472*8044SWilliam.Kucharski@Sun.COM break;
1473*8044SWilliam.Kucharski@Sun.COM case e1000_fc_full:
1474*8044SWilliam.Kucharski@Sun.COM /* Flow control (both RX and TX) is enabled by a software over-ride. */
1475*8044SWilliam.Kucharski@Sun.COM txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
1476*8044SWilliam.Kucharski@Sun.COM break;
1477*8044SWilliam.Kucharski@Sun.COM default:
1478*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow control param set incorrectly\n");
1479*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_CONFIG;
1480*8044SWilliam.Kucharski@Sun.COM break;
1481*8044SWilliam.Kucharski@Sun.COM }
1482*8044SWilliam.Kucharski@Sun.COM
1483*8044SWilliam.Kucharski@Sun.COM /* Since auto-negotiation is enabled, take the link out of reset (the link
1484*8044SWilliam.Kucharski@Sun.COM * will be in reset, because we previously reset the chip). This will
1485*8044SWilliam.Kucharski@Sun.COM * restart auto-negotiation. If auto-neogtiation is successful then the
1486*8044SWilliam.Kucharski@Sun.COM * link-up status bit will be set and the flow control enable bits (RFCE
1487*8044SWilliam.Kucharski@Sun.COM * and TFCE) will be set according to their negotiated value.
1488*8044SWilliam.Kucharski@Sun.COM */
1489*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Auto-negotiation enabled\n");
1490*8044SWilliam.Kucharski@Sun.COM
1491*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, TXCW, txcw);
1492*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
1493*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
1494*8044SWilliam.Kucharski@Sun.COM
1495*8044SWilliam.Kucharski@Sun.COM hw->txcw = txcw;
1496*8044SWilliam.Kucharski@Sun.COM mdelay(1);
1497*8044SWilliam.Kucharski@Sun.COM
1498*8044SWilliam.Kucharski@Sun.COM /* If we have a signal (the cable is plugged in) then poll for a "Link-Up"
1499*8044SWilliam.Kucharski@Sun.COM * indication in the Device Status Register. Time-out if a link isn't
1500*8044SWilliam.Kucharski@Sun.COM * seen in 500 milliseconds seconds (Auto-negotiation should complete in
1501*8044SWilliam.Kucharski@Sun.COM * less than 500 milliseconds even if the other end is doing it in SW).
1502*8044SWilliam.Kucharski@Sun.COM * For internal serdes, we just assume a signal is present, then poll.
1503*8044SWilliam.Kucharski@Sun.COM */
1504*8044SWilliam.Kucharski@Sun.COM if(hw->media_type == e1000_media_type_internal_serdes ||
1505*8044SWilliam.Kucharski@Sun.COM (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) {
1506*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Looking for Link\n");
1507*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
1508*8044SWilliam.Kucharski@Sun.COM mdelay(10);
1509*8044SWilliam.Kucharski@Sun.COM status = E1000_READ_REG(hw, STATUS);
1510*8044SWilliam.Kucharski@Sun.COM if(status & E1000_STATUS_LU) break;
1511*8044SWilliam.Kucharski@Sun.COM }
1512*8044SWilliam.Kucharski@Sun.COM if(i == (LINK_UP_TIMEOUT / 10)) {
1513*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Never got a valid link from auto-neg!!!\n");
1514*8044SWilliam.Kucharski@Sun.COM hw->autoneg_failed = 1;
1515*8044SWilliam.Kucharski@Sun.COM /* AutoNeg failed to achieve a link, so we'll call
1516*8044SWilliam.Kucharski@Sun.COM * e1000_check_for_link. This routine will force the link up if
1517*8044SWilliam.Kucharski@Sun.COM * we detect a signal. This will allow us to communicate with
1518*8044SWilliam.Kucharski@Sun.COM * non-autonegotiating link partners.
1519*8044SWilliam.Kucharski@Sun.COM */
1520*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_check_for_link(hw))) {
1521*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error while checking for link\n");
1522*8044SWilliam.Kucharski@Sun.COM return ret_val;
1523*8044SWilliam.Kucharski@Sun.COM }
1524*8044SWilliam.Kucharski@Sun.COM hw->autoneg_failed = 0;
1525*8044SWilliam.Kucharski@Sun.COM } else {
1526*8044SWilliam.Kucharski@Sun.COM hw->autoneg_failed = 0;
1527*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Valid Link Found\n");
1528*8044SWilliam.Kucharski@Sun.COM }
1529*8044SWilliam.Kucharski@Sun.COM } else {
1530*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("No Signal Detected\n");
1531*8044SWilliam.Kucharski@Sun.COM }
1532*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
1533*8044SWilliam.Kucharski@Sun.COM }
1534*8044SWilliam.Kucharski@Sun.COM
1535*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1536*8044SWilliam.Kucharski@Sun.COM * Detects which PHY is present and the speed and duplex
1537*8044SWilliam.Kucharski@Sun.COM *
1538*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
1539*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
1540*8044SWilliam.Kucharski@Sun.COM static int
1541*8044SWilliam.Kucharski@Sun.COM e1000_setup_copper_link(struct e1000_hw *hw)
1542*8044SWilliam.Kucharski@Sun.COM {
1543*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl;
1544*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
1545*8044SWilliam.Kucharski@Sun.COM uint16_t i;
1546*8044SWilliam.Kucharski@Sun.COM uint16_t phy_data;
1547*8044SWilliam.Kucharski@Sun.COM
1548*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_setup_copper_link");
1549*8044SWilliam.Kucharski@Sun.COM
1550*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
1551*8044SWilliam.Kucharski@Sun.COM /* With 82543, we need to force speed and duplex on the MAC equal to what
1552*8044SWilliam.Kucharski@Sun.COM * the PHY speed and duplex configuration is. In addition, we need to
1553*8044SWilliam.Kucharski@Sun.COM * perform a hardware reset on the PHY to take it out of reset.
1554*8044SWilliam.Kucharski@Sun.COM */
1555*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type > e1000_82543) {
1556*8044SWilliam.Kucharski@Sun.COM ctrl |= E1000_CTRL_SLU;
1557*8044SWilliam.Kucharski@Sun.COM ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
1558*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
1559*8044SWilliam.Kucharski@Sun.COM } else {
1560*8044SWilliam.Kucharski@Sun.COM ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
1561*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
1562*8044SWilliam.Kucharski@Sun.COM e1000_phy_hw_reset(hw);
1563*8044SWilliam.Kucharski@Sun.COM }
1564*8044SWilliam.Kucharski@Sun.COM
1565*8044SWilliam.Kucharski@Sun.COM /* Make sure we have a valid PHY */
1566*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_detect_gig_phy(hw))) {
1567*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error, did not detect valid phy.\n");
1568*8044SWilliam.Kucharski@Sun.COM return ret_val;
1569*8044SWilliam.Kucharski@Sun.COM }
1570*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
1571*8044SWilliam.Kucharski@Sun.COM
1572*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type <= e1000_82543 ||
1573*8044SWilliam.Kucharski@Sun.COM hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
1574*8044SWilliam.Kucharski@Sun.COM #if 0
1575*8044SWilliam.Kucharski@Sun.COM hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
1576*8044SWilliam.Kucharski@Sun.COM hw->phy_reset_disable = FALSE;
1577*8044SWilliam.Kucharski@Sun.COM
1578*8044SWilliam.Kucharski@Sun.COM if(!hw->phy_reset_disable) {
1579*8044SWilliam.Kucharski@Sun.COM #else
1580*8044SWilliam.Kucharski@Sun.COM hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
1581*8044SWilliam.Kucharski@Sun.COM #endif
1582*8044SWilliam.Kucharski@Sun.COM if (hw->phy_type == e1000_phy_igp) {
1583*8044SWilliam.Kucharski@Sun.COM
1584*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_phy_reset(hw))) {
1585*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error Resetting the PHY\n");
1586*8044SWilliam.Kucharski@Sun.COM return ret_val;
1587*8044SWilliam.Kucharski@Sun.COM }
1588*8044SWilliam.Kucharski@Sun.COM
1589*8044SWilliam.Kucharski@Sun.COM /* Wait 10ms for MAC to configure PHY from eeprom settings */
1590*8044SWilliam.Kucharski@Sun.COM mdelay(15);
1591*8044SWilliam.Kucharski@Sun.COM
1592*8044SWilliam.Kucharski@Sun.COM #if 0
1593*8044SWilliam.Kucharski@Sun.COM /* disable lplu d3 during driver init */
1594*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_set_d3_lplu_state(hw, FALSE))) {
1595*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error Disabling LPLU D3\n");
1596*8044SWilliam.Kucharski@Sun.COM return ret_val;
1597*8044SWilliam.Kucharski@Sun.COM }
1598*8044SWilliam.Kucharski@Sun.COM
1599*8044SWilliam.Kucharski@Sun.COM /* Configure mdi-mdix settings */
1600*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
1601*8044SWilliam.Kucharski@Sun.COM &phy_data)))
1602*8044SWilliam.Kucharski@Sun.COM return ret_val;
1603*8044SWilliam.Kucharski@Sun.COM
1604*8044SWilliam.Kucharski@Sun.COM if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
1605*8044SWilliam.Kucharski@Sun.COM hw->dsp_config_state = e1000_dsp_config_disabled;
1606*8044SWilliam.Kucharski@Sun.COM /* Force MDI for IGP B-0 PHY */
1607*8044SWilliam.Kucharski@Sun.COM phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX |
1608*8044SWilliam.Kucharski@Sun.COM IGP01E1000_PSCR_FORCE_MDI_MDIX);
1609*8044SWilliam.Kucharski@Sun.COM hw->mdix = 1;
1610*8044SWilliam.Kucharski@Sun.COM
1611*8044SWilliam.Kucharski@Sun.COM } else {
1612*8044SWilliam.Kucharski@Sun.COM hw->dsp_config_state = e1000_dsp_config_enabled;
1613*8044SWilliam.Kucharski@Sun.COM phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
1614*8044SWilliam.Kucharski@Sun.COM
1615*8044SWilliam.Kucharski@Sun.COM switch (hw->mdix) {
1616*8044SWilliam.Kucharski@Sun.COM case 1:
1617*8044SWilliam.Kucharski@Sun.COM phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
1618*8044SWilliam.Kucharski@Sun.COM break;
1619*8044SWilliam.Kucharski@Sun.COM case 2:
1620*8044SWilliam.Kucharski@Sun.COM phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
1621*8044SWilliam.Kucharski@Sun.COM break;
1622*8044SWilliam.Kucharski@Sun.COM case 0:
1623*8044SWilliam.Kucharski@Sun.COM default:
1624*8044SWilliam.Kucharski@Sun.COM phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
1625*8044SWilliam.Kucharski@Sun.COM break;
1626*8044SWilliam.Kucharski@Sun.COM }
1627*8044SWilliam.Kucharski@Sun.COM }
1628*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
1629*8044SWilliam.Kucharski@Sun.COM phy_data)))
1630*8044SWilliam.Kucharski@Sun.COM return ret_val;
1631*8044SWilliam.Kucharski@Sun.COM
1632*8044SWilliam.Kucharski@Sun.COM /* set auto-master slave resolution settings */
1633*8044SWilliam.Kucharski@Sun.COM e1000_ms_type phy_ms_setting = hw->master_slave;
1634*8044SWilliam.Kucharski@Sun.COM
1635*8044SWilliam.Kucharski@Sun.COM if(hw->ffe_config_state == e1000_ffe_config_active)
1636*8044SWilliam.Kucharski@Sun.COM hw->ffe_config_state = e1000_ffe_config_enabled;
1637*8044SWilliam.Kucharski@Sun.COM
1638*8044SWilliam.Kucharski@Sun.COM if(hw->dsp_config_state == e1000_dsp_config_activated)
1639*8044SWilliam.Kucharski@Sun.COM hw->dsp_config_state = e1000_dsp_config_enabled;
1640*8044SWilliam.Kucharski@Sun.COM #endif
1641*8044SWilliam.Kucharski@Sun.COM
1642*8044SWilliam.Kucharski@Sun.COM /* when autonegotiation advertisment is only 1000Mbps then we
1643*8044SWilliam.Kucharski@Sun.COM * should disable SmartSpeed and enable Auto MasterSlave
1644*8044SWilliam.Kucharski@Sun.COM * resolution as hardware default. */
1645*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
1646*8044SWilliam.Kucharski@Sun.COM /* Disable SmartSpeed */
1647*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw,
1648*8044SWilliam.Kucharski@Sun.COM IGP01E1000_PHY_PORT_CONFIG,
1649*8044SWilliam.Kucharski@Sun.COM &phy_data)))
1650*8044SWilliam.Kucharski@Sun.COM return ret_val;
1651*8044SWilliam.Kucharski@Sun.COM phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
1652*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw,
1653*8044SWilliam.Kucharski@Sun.COM IGP01E1000_PHY_PORT_CONFIG,
1654*8044SWilliam.Kucharski@Sun.COM phy_data)))
1655*8044SWilliam.Kucharski@Sun.COM return ret_val;
1656*8044SWilliam.Kucharski@Sun.COM /* Set auto Master/Slave resolution process */
1657*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL,
1658*8044SWilliam.Kucharski@Sun.COM &phy_data)))
1659*8044SWilliam.Kucharski@Sun.COM return ret_val;
1660*8044SWilliam.Kucharski@Sun.COM phy_data &= ~CR_1000T_MS_ENABLE;
1661*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
1662*8044SWilliam.Kucharski@Sun.COM phy_data)))
1663*8044SWilliam.Kucharski@Sun.COM return ret_val;
1664*8044SWilliam.Kucharski@Sun.COM }
1665*8044SWilliam.Kucharski@Sun.COM
1666*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL,
1667*8044SWilliam.Kucharski@Sun.COM &phy_data)))
1668*8044SWilliam.Kucharski@Sun.COM return ret_val;
1669*8044SWilliam.Kucharski@Sun.COM
1670*8044SWilliam.Kucharski@Sun.COM #if 0
1671*8044SWilliam.Kucharski@Sun.COM /* load defaults for future use */
1672*8044SWilliam.Kucharski@Sun.COM hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
1673*8044SWilliam.Kucharski@Sun.COM ((phy_data & CR_1000T_MS_VALUE) ?
1674*8044SWilliam.Kucharski@Sun.COM e1000_ms_force_master :
1675*8044SWilliam.Kucharski@Sun.COM e1000_ms_force_slave) :
1676*8044SWilliam.Kucharski@Sun.COM e1000_ms_auto;
1677*8044SWilliam.Kucharski@Sun.COM
1678*8044SWilliam.Kucharski@Sun.COM switch (phy_ms_setting) {
1679*8044SWilliam.Kucharski@Sun.COM case e1000_ms_force_master:
1680*8044SWilliam.Kucharski@Sun.COM phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
1681*8044SWilliam.Kucharski@Sun.COM break;
1682*8044SWilliam.Kucharski@Sun.COM case e1000_ms_force_slave:
1683*8044SWilliam.Kucharski@Sun.COM phy_data |= CR_1000T_MS_ENABLE;
1684*8044SWilliam.Kucharski@Sun.COM phy_data &= ~(CR_1000T_MS_VALUE);
1685*8044SWilliam.Kucharski@Sun.COM break;
1686*8044SWilliam.Kucharski@Sun.COM case e1000_ms_auto:
1687*8044SWilliam.Kucharski@Sun.COM phy_data &= ~CR_1000T_MS_ENABLE;
1688*8044SWilliam.Kucharski@Sun.COM default:
1689*8044SWilliam.Kucharski@Sun.COM break;
1690*8044SWilliam.Kucharski@Sun.COM }
1691*8044SWilliam.Kucharski@Sun.COM #endif
1692*8044SWilliam.Kucharski@Sun.COM
1693*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
1694*8044SWilliam.Kucharski@Sun.COM phy_data)))
1695*8044SWilliam.Kucharski@Sun.COM return ret_val;
1696*8044SWilliam.Kucharski@Sun.COM } else {
1697*8044SWilliam.Kucharski@Sun.COM /* Enable CRS on TX. This must be set for half-duplex operation. */
1698*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
1699*8044SWilliam.Kucharski@Sun.COM &phy_data)))
1700*8044SWilliam.Kucharski@Sun.COM return ret_val;
1701*8044SWilliam.Kucharski@Sun.COM
1702*8044SWilliam.Kucharski@Sun.COM phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
1703*8044SWilliam.Kucharski@Sun.COM
1704*8044SWilliam.Kucharski@Sun.COM /* Options:
1705*8044SWilliam.Kucharski@Sun.COM * MDI/MDI-X = 0 (default)
1706*8044SWilliam.Kucharski@Sun.COM * 0 - Auto for all speeds
1707*8044SWilliam.Kucharski@Sun.COM * 1 - MDI mode
1708*8044SWilliam.Kucharski@Sun.COM * 2 - MDI-X mode
1709*8044SWilliam.Kucharski@Sun.COM * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
1710*8044SWilliam.Kucharski@Sun.COM */
1711*8044SWilliam.Kucharski@Sun.COM #if 0
1712*8044SWilliam.Kucharski@Sun.COM phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
1713*8044SWilliam.Kucharski@Sun.COM
1714*8044SWilliam.Kucharski@Sun.COM switch (hw->mdix) {
1715*8044SWilliam.Kucharski@Sun.COM case 1:
1716*8044SWilliam.Kucharski@Sun.COM phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
1717*8044SWilliam.Kucharski@Sun.COM break;
1718*8044SWilliam.Kucharski@Sun.COM case 2:
1719*8044SWilliam.Kucharski@Sun.COM phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
1720*8044SWilliam.Kucharski@Sun.COM break;
1721*8044SWilliam.Kucharski@Sun.COM case 3:
1722*8044SWilliam.Kucharski@Sun.COM phy_data |= M88E1000_PSCR_AUTO_X_1000T;
1723*8044SWilliam.Kucharski@Sun.COM break;
1724*8044SWilliam.Kucharski@Sun.COM case 0:
1725*8044SWilliam.Kucharski@Sun.COM default:
1726*8044SWilliam.Kucharski@Sun.COM #endif
1727*8044SWilliam.Kucharski@Sun.COM phy_data |= M88E1000_PSCR_AUTO_X_MODE;
1728*8044SWilliam.Kucharski@Sun.COM #if 0
1729*8044SWilliam.Kucharski@Sun.COM break;
1730*8044SWilliam.Kucharski@Sun.COM }
1731*8044SWilliam.Kucharski@Sun.COM #endif
1732*8044SWilliam.Kucharski@Sun.COM
1733*8044SWilliam.Kucharski@Sun.COM /* Options:
1734*8044SWilliam.Kucharski@Sun.COM * disable_polarity_correction = 0 (default)
1735*8044SWilliam.Kucharski@Sun.COM * Automatic Correction for Reversed Cable Polarity
1736*8044SWilliam.Kucharski@Sun.COM * 0 - Disabled
1737*8044SWilliam.Kucharski@Sun.COM * 1 - Enabled
1738*8044SWilliam.Kucharski@Sun.COM */
1739*8044SWilliam.Kucharski@Sun.COM phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
1740*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
1741*8044SWilliam.Kucharski@Sun.COM phy_data)))
1742*8044SWilliam.Kucharski@Sun.COM return ret_val;
1743*8044SWilliam.Kucharski@Sun.COM
1744*8044SWilliam.Kucharski@Sun.COM /* Force TX_CLK in the Extended PHY Specific Control Register
1745*8044SWilliam.Kucharski@Sun.COM * to 25MHz clock.
1746*8044SWilliam.Kucharski@Sun.COM */
1747*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
1748*8044SWilliam.Kucharski@Sun.COM &phy_data)))
1749*8044SWilliam.Kucharski@Sun.COM return ret_val;
1750*8044SWilliam.Kucharski@Sun.COM
1751*8044SWilliam.Kucharski@Sun.COM phy_data |= M88E1000_EPSCR_TX_CLK_25;
1752*8044SWilliam.Kucharski@Sun.COM
1753*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
1754*8044SWilliam.Kucharski@Sun.COM if (hw->phy_revision < M88E1011_I_REV_4) {
1755*8044SWilliam.Kucharski@Sun.COM #endif
1756*8044SWilliam.Kucharski@Sun.COM /* Configure Master and Slave downshift values */
1757*8044SWilliam.Kucharski@Sun.COM phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
1758*8044SWilliam.Kucharski@Sun.COM M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
1759*8044SWilliam.Kucharski@Sun.COM phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
1760*8044SWilliam.Kucharski@Sun.COM M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
1761*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw,
1762*8044SWilliam.Kucharski@Sun.COM M88E1000_EXT_PHY_SPEC_CTRL,
1763*8044SWilliam.Kucharski@Sun.COM phy_data)))
1764*8044SWilliam.Kucharski@Sun.COM return ret_val;
1765*8044SWilliam.Kucharski@Sun.COM }
1766*8044SWilliam.Kucharski@Sun.COM
1767*8044SWilliam.Kucharski@Sun.COM /* SW Reset the PHY so all changes take effect */
1768*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_phy_reset(hw))) {
1769*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error Resetting the PHY\n");
1770*8044SWilliam.Kucharski@Sun.COM return ret_val;
1771*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
1772*8044SWilliam.Kucharski@Sun.COM }
1773*8044SWilliam.Kucharski@Sun.COM #endif
1774*8044SWilliam.Kucharski@Sun.COM }
1775*8044SWilliam.Kucharski@Sun.COM
1776*8044SWilliam.Kucharski@Sun.COM /* Options:
1777*8044SWilliam.Kucharski@Sun.COM * autoneg = 1 (default)
1778*8044SWilliam.Kucharski@Sun.COM * PHY will advertise value(s) parsed from
1779*8044SWilliam.Kucharski@Sun.COM * autoneg_advertised and fc
1780*8044SWilliam.Kucharski@Sun.COM * autoneg = 0
1781*8044SWilliam.Kucharski@Sun.COM * PHY will be set to 10H, 10F, 100H, or 100F
1782*8044SWilliam.Kucharski@Sun.COM * depending on value parsed from forced_speed_duplex.
1783*8044SWilliam.Kucharski@Sun.COM */
1784*8044SWilliam.Kucharski@Sun.COM
1785*8044SWilliam.Kucharski@Sun.COM /* Is autoneg enabled? This is enabled by default or by software
1786*8044SWilliam.Kucharski@Sun.COM * override. If so, call e1000_phy_setup_autoneg routine to parse the
1787*8044SWilliam.Kucharski@Sun.COM * autoneg_advertised and fc options. If autoneg is NOT enabled, then
1788*8044SWilliam.Kucharski@Sun.COM * the user should have provided a speed/duplex override. If so, then
1789*8044SWilliam.Kucharski@Sun.COM * call e1000_phy_force_speed_duplex to parse and set this up.
1790*8044SWilliam.Kucharski@Sun.COM */
1791*8044SWilliam.Kucharski@Sun.COM /* Perform some bounds checking on the hw->autoneg_advertised
1792*8044SWilliam.Kucharski@Sun.COM * parameter. If this variable is zero, then set it to the default.
1793*8044SWilliam.Kucharski@Sun.COM */
1794*8044SWilliam.Kucharski@Sun.COM hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
1795*8044SWilliam.Kucharski@Sun.COM
1796*8044SWilliam.Kucharski@Sun.COM /* If autoneg_advertised is zero, we assume it was not defaulted
1797*8044SWilliam.Kucharski@Sun.COM * by the calling code so we set to advertise full capability.
1798*8044SWilliam.Kucharski@Sun.COM */
1799*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_advertised == 0)
1800*8044SWilliam.Kucharski@Sun.COM hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
1801*8044SWilliam.Kucharski@Sun.COM
1802*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
1803*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_phy_setup_autoneg(hw))) {
1804*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error Setting up Auto-Negotiation\n");
1805*8044SWilliam.Kucharski@Sun.COM return ret_val;
1806*8044SWilliam.Kucharski@Sun.COM }
1807*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Restarting Auto-Neg\n");
1808*8044SWilliam.Kucharski@Sun.COM
1809*8044SWilliam.Kucharski@Sun.COM /* Restart auto-negotiation by setting the Auto Neg Enable bit and
1810*8044SWilliam.Kucharski@Sun.COM * the Auto Neg Restart bit in the PHY control register.
1811*8044SWilliam.Kucharski@Sun.COM */
1812*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data)))
1813*8044SWilliam.Kucharski@Sun.COM return ret_val;
1814*8044SWilliam.Kucharski@Sun.COM
1815*8044SWilliam.Kucharski@Sun.COM phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
1816*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data)))
1817*8044SWilliam.Kucharski@Sun.COM return ret_val;
1818*8044SWilliam.Kucharski@Sun.COM
1819*8044SWilliam.Kucharski@Sun.COM #if 0
1820*8044SWilliam.Kucharski@Sun.COM /* Does the user want to wait for Auto-Neg to complete here, or
1821*8044SWilliam.Kucharski@Sun.COM * check at a later time (for example, callback routine).
1822*8044SWilliam.Kucharski@Sun.COM */
1823*8044SWilliam.Kucharski@Sun.COM if(hw->wait_autoneg_complete) {
1824*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_wait_autoneg(hw))) {
1825*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error while waiting for autoneg to complete\n");
1826*8044SWilliam.Kucharski@Sun.COM return ret_val;
1827*8044SWilliam.Kucharski@Sun.COM }
1828*8044SWilliam.Kucharski@Sun.COM }
1829*8044SWilliam.Kucharski@Sun.COM #else
1830*8044SWilliam.Kucharski@Sun.COM /* If we do not wait for autonegotiation to complete I
1831*8044SWilliam.Kucharski@Sun.COM * do not see a valid link status.
1832*8044SWilliam.Kucharski@Sun.COM */
1833*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_wait_autoneg(hw))) {
1834*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error while waiting for autoneg to complete\n");
1835*8044SWilliam.Kucharski@Sun.COM return ret_val;
1836*8044SWilliam.Kucharski@Sun.COM }
1837*8044SWilliam.Kucharski@Sun.COM #endif
1838*8044SWilliam.Kucharski@Sun.COM } /* !hw->phy_reset_disable */
1839*8044SWilliam.Kucharski@Sun.COM
1840*8044SWilliam.Kucharski@Sun.COM /* Check link status. Wait up to 100 microseconds for link to become
1841*8044SWilliam.Kucharski@Sun.COM * valid.
1842*8044SWilliam.Kucharski@Sun.COM */
1843*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < 10; i++) {
1844*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
1845*8044SWilliam.Kucharski@Sun.COM return ret_val;
1846*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
1847*8044SWilliam.Kucharski@Sun.COM return ret_val;
1848*8044SWilliam.Kucharski@Sun.COM
1849*8044SWilliam.Kucharski@Sun.COM if(phy_data & MII_SR_LINK_STATUS) {
1850*8044SWilliam.Kucharski@Sun.COM /* We have link, so we need to finish the config process:
1851*8044SWilliam.Kucharski@Sun.COM * 1) Set up the MAC to the current PHY speed/duplex
1852*8044SWilliam.Kucharski@Sun.COM * if we are on 82543. If we
1853*8044SWilliam.Kucharski@Sun.COM * are on newer silicon, we only need to configure
1854*8044SWilliam.Kucharski@Sun.COM * collision distance in the Transmit Control Register.
1855*8044SWilliam.Kucharski@Sun.COM * 2) Set up flow control on the MAC to that established with
1856*8044SWilliam.Kucharski@Sun.COM * the link partner.
1857*8044SWilliam.Kucharski@Sun.COM */
1858*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type >= e1000_82544) {
1859*8044SWilliam.Kucharski@Sun.COM e1000_config_collision_dist(hw);
1860*8044SWilliam.Kucharski@Sun.COM } else {
1861*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_config_mac_to_phy(hw))) {
1862*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error configuring MAC to PHY settings\n");
1863*8044SWilliam.Kucharski@Sun.COM return ret_val;
1864*8044SWilliam.Kucharski@Sun.COM }
1865*8044SWilliam.Kucharski@Sun.COM }
1866*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_config_fc_after_link_up(hw))) {
1867*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error Configuring Flow Control\n");
1868*8044SWilliam.Kucharski@Sun.COM return ret_val;
1869*8044SWilliam.Kucharski@Sun.COM }
1870*8044SWilliam.Kucharski@Sun.COM #if 0
1871*8044SWilliam.Kucharski@Sun.COM if(hw->phy_type == e1000_phy_igp) {
1872*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_config_dsp_after_link_change(hw, TRUE))) {
1873*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error Configuring DSP after link up\n");
1874*8044SWilliam.Kucharski@Sun.COM return ret_val;
1875*8044SWilliam.Kucharski@Sun.COM }
1876*8044SWilliam.Kucharski@Sun.COM }
1877*8044SWilliam.Kucharski@Sun.COM #endif
1878*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Valid link established!!!\n");
1879*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
1880*8044SWilliam.Kucharski@Sun.COM }
1881*8044SWilliam.Kucharski@Sun.COM udelay(10);
1882*8044SWilliam.Kucharski@Sun.COM }
1883*8044SWilliam.Kucharski@Sun.COM
1884*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Unable to establish link!!!\n");
1885*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_NOLINK;
1886*8044SWilliam.Kucharski@Sun.COM }
1887*8044SWilliam.Kucharski@Sun.COM
1888*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
1889*8044SWilliam.Kucharski@Sun.COM * Configures PHY autoneg and flow control advertisement settings
1890*8044SWilliam.Kucharski@Sun.COM *
1891*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
1892*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
1893*8044SWilliam.Kucharski@Sun.COM static int
1894*8044SWilliam.Kucharski@Sun.COM e1000_phy_setup_autoneg(struct e1000_hw *hw)
1895*8044SWilliam.Kucharski@Sun.COM {
1896*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
1897*8044SWilliam.Kucharski@Sun.COM uint16_t mii_autoneg_adv_reg;
1898*8044SWilliam.Kucharski@Sun.COM uint16_t mii_1000t_ctrl_reg;
1899*8044SWilliam.Kucharski@Sun.COM
1900*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_phy_setup_autoneg");
1901*8044SWilliam.Kucharski@Sun.COM
1902*8044SWilliam.Kucharski@Sun.COM /* Read the MII Auto-Neg Advertisement Register (Address 4). */
1903*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
1904*8044SWilliam.Kucharski@Sun.COM &mii_autoneg_adv_reg)))
1905*8044SWilliam.Kucharski@Sun.COM return ret_val;
1906*8044SWilliam.Kucharski@Sun.COM
1907*8044SWilliam.Kucharski@Sun.COM /* Read the MII 1000Base-T Control Register (Address 9). */
1908*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg)))
1909*8044SWilliam.Kucharski@Sun.COM return ret_val;
1910*8044SWilliam.Kucharski@Sun.COM
1911*8044SWilliam.Kucharski@Sun.COM /* Need to parse both autoneg_advertised and fc and set up
1912*8044SWilliam.Kucharski@Sun.COM * the appropriate PHY registers. First we will parse for
1913*8044SWilliam.Kucharski@Sun.COM * autoneg_advertised software override. Since we can advertise
1914*8044SWilliam.Kucharski@Sun.COM * a plethora of combinations, we need to check each bit
1915*8044SWilliam.Kucharski@Sun.COM * individually.
1916*8044SWilliam.Kucharski@Sun.COM */
1917*8044SWilliam.Kucharski@Sun.COM
1918*8044SWilliam.Kucharski@Sun.COM /* First we clear all the 10/100 mb speed bits in the Auto-Neg
1919*8044SWilliam.Kucharski@Sun.COM * Advertisement Register (Address 4) and the 1000 mb speed bits in
1920*8044SWilliam.Kucharski@Sun.COM * the 1000Base-T Control Register (Address 9).
1921*8044SWilliam.Kucharski@Sun.COM */
1922*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
1923*8044SWilliam.Kucharski@Sun.COM mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
1924*8044SWilliam.Kucharski@Sun.COM
1925*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised);
1926*8044SWilliam.Kucharski@Sun.COM
1927*8044SWilliam.Kucharski@Sun.COM /* Do we want to advertise 10 Mb Half Duplex? */
1928*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_advertised & ADVERTISE_10_HALF) {
1929*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Advertise 10mb Half duplex\n");
1930*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
1931*8044SWilliam.Kucharski@Sun.COM }
1932*8044SWilliam.Kucharski@Sun.COM
1933*8044SWilliam.Kucharski@Sun.COM /* Do we want to advertise 10 Mb Full Duplex? */
1934*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_advertised & ADVERTISE_10_FULL) {
1935*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Advertise 10mb Full duplex\n");
1936*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
1937*8044SWilliam.Kucharski@Sun.COM }
1938*8044SWilliam.Kucharski@Sun.COM
1939*8044SWilliam.Kucharski@Sun.COM /* Do we want to advertise 100 Mb Half Duplex? */
1940*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_advertised & ADVERTISE_100_HALF) {
1941*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Advertise 100mb Half duplex\n");
1942*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
1943*8044SWilliam.Kucharski@Sun.COM }
1944*8044SWilliam.Kucharski@Sun.COM
1945*8044SWilliam.Kucharski@Sun.COM /* Do we want to advertise 100 Mb Full Duplex? */
1946*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_advertised & ADVERTISE_100_FULL) {
1947*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Advertise 100mb Full duplex\n");
1948*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
1949*8044SWilliam.Kucharski@Sun.COM }
1950*8044SWilliam.Kucharski@Sun.COM
1951*8044SWilliam.Kucharski@Sun.COM /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
1952*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_advertised & ADVERTISE_1000_HALF) {
1953*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");
1954*8044SWilliam.Kucharski@Sun.COM }
1955*8044SWilliam.Kucharski@Sun.COM
1956*8044SWilliam.Kucharski@Sun.COM /* Do we want to advertise 1000 Mb Full Duplex? */
1957*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_advertised & ADVERTISE_1000_FULL) {
1958*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Advertise 1000mb Full duplex\n");
1959*8044SWilliam.Kucharski@Sun.COM mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
1960*8044SWilliam.Kucharski@Sun.COM }
1961*8044SWilliam.Kucharski@Sun.COM
1962*8044SWilliam.Kucharski@Sun.COM /* Check for a software override of the flow control settings, and
1963*8044SWilliam.Kucharski@Sun.COM * setup the PHY advertisement registers accordingly. If
1964*8044SWilliam.Kucharski@Sun.COM * auto-negotiation is enabled, then software will have to set the
1965*8044SWilliam.Kucharski@Sun.COM * "PAUSE" bits to the correct value in the Auto-Negotiation
1966*8044SWilliam.Kucharski@Sun.COM * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
1967*8044SWilliam.Kucharski@Sun.COM *
1968*8044SWilliam.Kucharski@Sun.COM * The possible values of the "fc" parameter are:
1969*8044SWilliam.Kucharski@Sun.COM * 0: Flow control is completely disabled
1970*8044SWilliam.Kucharski@Sun.COM * 1: Rx flow control is enabled (we can receive pause frames
1971*8044SWilliam.Kucharski@Sun.COM * but not send pause frames).
1972*8044SWilliam.Kucharski@Sun.COM * 2: Tx flow control is enabled (we can send pause frames
1973*8044SWilliam.Kucharski@Sun.COM * but we do not support receiving pause frames).
1974*8044SWilliam.Kucharski@Sun.COM * 3: Both Rx and TX flow control (symmetric) are enabled.
1975*8044SWilliam.Kucharski@Sun.COM * other: No software override. The flow control configuration
1976*8044SWilliam.Kucharski@Sun.COM * in the EEPROM is used.
1977*8044SWilliam.Kucharski@Sun.COM */
1978*8044SWilliam.Kucharski@Sun.COM switch (hw->fc) {
1979*8044SWilliam.Kucharski@Sun.COM case e1000_fc_none: /* 0 */
1980*8044SWilliam.Kucharski@Sun.COM /* Flow control (RX & TX) is completely disabled by a
1981*8044SWilliam.Kucharski@Sun.COM * software over-ride.
1982*8044SWilliam.Kucharski@Sun.COM */
1983*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
1984*8044SWilliam.Kucharski@Sun.COM break;
1985*8044SWilliam.Kucharski@Sun.COM case e1000_fc_rx_pause: /* 1 */
1986*8044SWilliam.Kucharski@Sun.COM /* RX Flow control is enabled, and TX Flow control is
1987*8044SWilliam.Kucharski@Sun.COM * disabled, by a software over-ride.
1988*8044SWilliam.Kucharski@Sun.COM */
1989*8044SWilliam.Kucharski@Sun.COM /* Since there really isn't a way to advertise that we are
1990*8044SWilliam.Kucharski@Sun.COM * capable of RX Pause ONLY, we will advertise that we
1991*8044SWilliam.Kucharski@Sun.COM * support both symmetric and asymmetric RX PAUSE. Later
1992*8044SWilliam.Kucharski@Sun.COM * (in e1000_config_fc_after_link_up) we will disable the
1993*8044SWilliam.Kucharski@Sun.COM *hw's ability to send PAUSE frames.
1994*8044SWilliam.Kucharski@Sun.COM */
1995*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
1996*8044SWilliam.Kucharski@Sun.COM break;
1997*8044SWilliam.Kucharski@Sun.COM case e1000_fc_tx_pause: /* 2 */
1998*8044SWilliam.Kucharski@Sun.COM /* TX Flow control is enabled, and RX Flow control is
1999*8044SWilliam.Kucharski@Sun.COM * disabled, by a software over-ride.
2000*8044SWilliam.Kucharski@Sun.COM */
2001*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
2002*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
2003*8044SWilliam.Kucharski@Sun.COM break;
2004*8044SWilliam.Kucharski@Sun.COM case e1000_fc_full: /* 3 */
2005*8044SWilliam.Kucharski@Sun.COM /* Flow control (both RX and TX) is enabled by a software
2006*8044SWilliam.Kucharski@Sun.COM * over-ride.
2007*8044SWilliam.Kucharski@Sun.COM */
2008*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
2009*8044SWilliam.Kucharski@Sun.COM break;
2010*8044SWilliam.Kucharski@Sun.COM default:
2011*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow control param set incorrectly\n");
2012*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_CONFIG;
2013*8044SWilliam.Kucharski@Sun.COM }
2014*8044SWilliam.Kucharski@Sun.COM
2015*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV,
2016*8044SWilliam.Kucharski@Sun.COM mii_autoneg_adv_reg)))
2017*8044SWilliam.Kucharski@Sun.COM return ret_val;
2018*8044SWilliam.Kucharski@Sun.COM
2019*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
2020*8044SWilliam.Kucharski@Sun.COM
2021*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg)))
2022*8044SWilliam.Kucharski@Sun.COM return ret_val;
2023*8044SWilliam.Kucharski@Sun.COM
2024*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
2025*8044SWilliam.Kucharski@Sun.COM }
2026*8044SWilliam.Kucharski@Sun.COM
2027*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2028*8044SWilliam.Kucharski@Sun.COM * Sets the collision distance in the Transmit Control register
2029*8044SWilliam.Kucharski@Sun.COM *
2030*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2031*8044SWilliam.Kucharski@Sun.COM *
2032*8044SWilliam.Kucharski@Sun.COM * Link should have been established previously. Reads the speed and duplex
2033*8044SWilliam.Kucharski@Sun.COM * information from the Device Status register.
2034*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2035*8044SWilliam.Kucharski@Sun.COM static void
2036*8044SWilliam.Kucharski@Sun.COM e1000_config_collision_dist(struct e1000_hw *hw)
2037*8044SWilliam.Kucharski@Sun.COM {
2038*8044SWilliam.Kucharski@Sun.COM uint32_t tctl;
2039*8044SWilliam.Kucharski@Sun.COM
2040*8044SWilliam.Kucharski@Sun.COM tctl = E1000_READ_REG(hw, TCTL);
2041*8044SWilliam.Kucharski@Sun.COM
2042*8044SWilliam.Kucharski@Sun.COM tctl &= ~E1000_TCTL_COLD;
2043*8044SWilliam.Kucharski@Sun.COM tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
2044*8044SWilliam.Kucharski@Sun.COM
2045*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, TCTL, tctl);
2046*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
2047*8044SWilliam.Kucharski@Sun.COM }
2048*8044SWilliam.Kucharski@Sun.COM
2049*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2050*8044SWilliam.Kucharski@Sun.COM * Sets MAC speed and duplex settings to reflect the those in the PHY
2051*8044SWilliam.Kucharski@Sun.COM *
2052*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2053*8044SWilliam.Kucharski@Sun.COM * mii_reg - data to write to the MII control register
2054*8044SWilliam.Kucharski@Sun.COM *
2055*8044SWilliam.Kucharski@Sun.COM * The contents of the PHY register containing the needed information need to
2056*8044SWilliam.Kucharski@Sun.COM * be passed in.
2057*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2058*8044SWilliam.Kucharski@Sun.COM static int
2059*8044SWilliam.Kucharski@Sun.COM e1000_config_mac_to_phy(struct e1000_hw *hw)
2060*8044SWilliam.Kucharski@Sun.COM {
2061*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl;
2062*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
2063*8044SWilliam.Kucharski@Sun.COM uint16_t phy_data;
2064*8044SWilliam.Kucharski@Sun.COM
2065*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_config_mac_to_phy");
2066*8044SWilliam.Kucharski@Sun.COM
2067*8044SWilliam.Kucharski@Sun.COM /* Read the Device Control Register and set the bits to Force Speed
2068*8044SWilliam.Kucharski@Sun.COM * and Duplex.
2069*8044SWilliam.Kucharski@Sun.COM */
2070*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
2071*8044SWilliam.Kucharski@Sun.COM ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
2072*8044SWilliam.Kucharski@Sun.COM ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
2073*8044SWilliam.Kucharski@Sun.COM
2074*8044SWilliam.Kucharski@Sun.COM /* Set up duplex in the Device Control and Transmit Control
2075*8044SWilliam.Kucharski@Sun.COM * registers depending on negotiated values.
2076*8044SWilliam.Kucharski@Sun.COM */
2077*8044SWilliam.Kucharski@Sun.COM if (hw->phy_type == e1000_phy_igp) {
2078*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
2079*8044SWilliam.Kucharski@Sun.COM &phy_data)))
2080*8044SWilliam.Kucharski@Sun.COM return ret_val;
2081*8044SWilliam.Kucharski@Sun.COM
2082*8044SWilliam.Kucharski@Sun.COM if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD;
2083*8044SWilliam.Kucharski@Sun.COM else ctrl &= ~E1000_CTRL_FD;
2084*8044SWilliam.Kucharski@Sun.COM
2085*8044SWilliam.Kucharski@Sun.COM e1000_config_collision_dist(hw);
2086*8044SWilliam.Kucharski@Sun.COM
2087*8044SWilliam.Kucharski@Sun.COM /* Set up speed in the Device Control register depending on
2088*8044SWilliam.Kucharski@Sun.COM * negotiated values.
2089*8044SWilliam.Kucharski@Sun.COM */
2090*8044SWilliam.Kucharski@Sun.COM if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
2091*8044SWilliam.Kucharski@Sun.COM IGP01E1000_PSSR_SPEED_1000MBPS)
2092*8044SWilliam.Kucharski@Sun.COM ctrl |= E1000_CTRL_SPD_1000;
2093*8044SWilliam.Kucharski@Sun.COM else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
2094*8044SWilliam.Kucharski@Sun.COM IGP01E1000_PSSR_SPEED_100MBPS)
2095*8044SWilliam.Kucharski@Sun.COM ctrl |= E1000_CTRL_SPD_100;
2096*8044SWilliam.Kucharski@Sun.COM } else {
2097*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
2098*8044SWilliam.Kucharski@Sun.COM &phy_data)))
2099*8044SWilliam.Kucharski@Sun.COM return ret_val;
2100*8044SWilliam.Kucharski@Sun.COM
2101*8044SWilliam.Kucharski@Sun.COM if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD;
2102*8044SWilliam.Kucharski@Sun.COM else ctrl &= ~E1000_CTRL_FD;
2103*8044SWilliam.Kucharski@Sun.COM
2104*8044SWilliam.Kucharski@Sun.COM e1000_config_collision_dist(hw);
2105*8044SWilliam.Kucharski@Sun.COM
2106*8044SWilliam.Kucharski@Sun.COM /* Set up speed in the Device Control register depending on
2107*8044SWilliam.Kucharski@Sun.COM * negotiated values.
2108*8044SWilliam.Kucharski@Sun.COM */
2109*8044SWilliam.Kucharski@Sun.COM if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
2110*8044SWilliam.Kucharski@Sun.COM ctrl |= E1000_CTRL_SPD_1000;
2111*8044SWilliam.Kucharski@Sun.COM else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
2112*8044SWilliam.Kucharski@Sun.COM ctrl |= E1000_CTRL_SPD_100;
2113*8044SWilliam.Kucharski@Sun.COM }
2114*8044SWilliam.Kucharski@Sun.COM /* Write the configured values back to the Device Control Reg. */
2115*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
2116*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
2117*8044SWilliam.Kucharski@Sun.COM }
2118*8044SWilliam.Kucharski@Sun.COM
2119*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2120*8044SWilliam.Kucharski@Sun.COM * Forces the MAC's flow control settings.
2121*8044SWilliam.Kucharski@Sun.COM *
2122*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2123*8044SWilliam.Kucharski@Sun.COM *
2124*8044SWilliam.Kucharski@Sun.COM * Sets the TFCE and RFCE bits in the device control register to reflect
2125*8044SWilliam.Kucharski@Sun.COM * the adapter settings. TFCE and RFCE need to be explicitly set by
2126*8044SWilliam.Kucharski@Sun.COM * software when a Copper PHY is used because autonegotiation is managed
2127*8044SWilliam.Kucharski@Sun.COM * by the PHY rather than the MAC. Software must also configure these
2128*8044SWilliam.Kucharski@Sun.COM * bits when link is forced on a fiber connection.
2129*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
2130*8044SWilliam.Kucharski@Sun.COM static int
2131*8044SWilliam.Kucharski@Sun.COM e1000_force_mac_fc(struct e1000_hw *hw)
2132*8044SWilliam.Kucharski@Sun.COM {
2133*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl;
2134*8044SWilliam.Kucharski@Sun.COM
2135*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_force_mac_fc");
2136*8044SWilliam.Kucharski@Sun.COM
2137*8044SWilliam.Kucharski@Sun.COM /* Get the current configuration of the Device Control Register */
2138*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
2139*8044SWilliam.Kucharski@Sun.COM
2140*8044SWilliam.Kucharski@Sun.COM /* Because we didn't get link via the internal auto-negotiation
2141*8044SWilliam.Kucharski@Sun.COM * mechanism (we either forced link or we got link via PHY
2142*8044SWilliam.Kucharski@Sun.COM * auto-neg), we have to manually enable/disable transmit an
2143*8044SWilliam.Kucharski@Sun.COM * receive flow control.
2144*8044SWilliam.Kucharski@Sun.COM *
2145*8044SWilliam.Kucharski@Sun.COM * The "Case" statement below enables/disable flow control
2146*8044SWilliam.Kucharski@Sun.COM * according to the "hw->fc" parameter.
2147*8044SWilliam.Kucharski@Sun.COM *
2148*8044SWilliam.Kucharski@Sun.COM * The possible values of the "fc" parameter are:
2149*8044SWilliam.Kucharski@Sun.COM * 0: Flow control is completely disabled
2150*8044SWilliam.Kucharski@Sun.COM * 1: Rx flow control is enabled (we can receive pause
2151*8044SWilliam.Kucharski@Sun.COM * frames but not send pause frames).
2152*8044SWilliam.Kucharski@Sun.COM * 2: Tx flow control is enabled (we can send pause frames
2153*8044SWilliam.Kucharski@Sun.COM * frames but we do not receive pause frames).
2154*8044SWilliam.Kucharski@Sun.COM * 3: Both Rx and TX flow control (symmetric) is enabled.
2155*8044SWilliam.Kucharski@Sun.COM * other: No other values should be possible at this point.
2156*8044SWilliam.Kucharski@Sun.COM */
2157*8044SWilliam.Kucharski@Sun.COM
2158*8044SWilliam.Kucharski@Sun.COM switch (hw->fc) {
2159*8044SWilliam.Kucharski@Sun.COM case e1000_fc_none:
2160*8044SWilliam.Kucharski@Sun.COM ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
2161*8044SWilliam.Kucharski@Sun.COM break;
2162*8044SWilliam.Kucharski@Sun.COM case e1000_fc_rx_pause:
2163*8044SWilliam.Kucharski@Sun.COM ctrl &= (~E1000_CTRL_TFCE);
2164*8044SWilliam.Kucharski@Sun.COM ctrl |= E1000_CTRL_RFCE;
2165*8044SWilliam.Kucharski@Sun.COM break;
2166*8044SWilliam.Kucharski@Sun.COM case e1000_fc_tx_pause:
2167*8044SWilliam.Kucharski@Sun.COM ctrl &= (~E1000_CTRL_RFCE);
2168*8044SWilliam.Kucharski@Sun.COM ctrl |= E1000_CTRL_TFCE;
2169*8044SWilliam.Kucharski@Sun.COM break;
2170*8044SWilliam.Kucharski@Sun.COM case e1000_fc_full:
2171*8044SWilliam.Kucharski@Sun.COM ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
2172*8044SWilliam.Kucharski@Sun.COM break;
2173*8044SWilliam.Kucharski@Sun.COM default:
2174*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow control param set incorrectly\n");
2175*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_CONFIG;
2176*8044SWilliam.Kucharski@Sun.COM }
2177*8044SWilliam.Kucharski@Sun.COM
2178*8044SWilliam.Kucharski@Sun.COM /* Disable TX Flow Control for 82542 (rev 2.0) */
2179*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type == e1000_82542_rev2_0)
2180*8044SWilliam.Kucharski@Sun.COM ctrl &= (~E1000_CTRL_TFCE);
2181*8044SWilliam.Kucharski@Sun.COM
2182*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
2183*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
2184*8044SWilliam.Kucharski@Sun.COM }
2185*8044SWilliam.Kucharski@Sun.COM
2186*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2187*8044SWilliam.Kucharski@Sun.COM * Configures flow control settings after link is established
2188*8044SWilliam.Kucharski@Sun.COM *
2189*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2190*8044SWilliam.Kucharski@Sun.COM *
2191*8044SWilliam.Kucharski@Sun.COM * Should be called immediately after a valid link has been established.
2192*8044SWilliam.Kucharski@Sun.COM * Forces MAC flow control settings if link was forced. When in MII/GMII mode
2193*8044SWilliam.Kucharski@Sun.COM * and autonegotiation is enabled, the MAC flow control settings will be set
2194*8044SWilliam.Kucharski@Sun.COM * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
2195*8044SWilliam.Kucharski@Sun.COM * and RFCE bits will be automaticaly set to the negotiated flow control mode.
2196*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
2197*8044SWilliam.Kucharski@Sun.COM static int
2198*8044SWilliam.Kucharski@Sun.COM e1000_config_fc_after_link_up(struct e1000_hw *hw)
2199*8044SWilliam.Kucharski@Sun.COM {
2200*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
2201*8044SWilliam.Kucharski@Sun.COM uint16_t mii_status_reg;
2202*8044SWilliam.Kucharski@Sun.COM uint16_t mii_nway_adv_reg;
2203*8044SWilliam.Kucharski@Sun.COM uint16_t mii_nway_lp_ability_reg;
2204*8044SWilliam.Kucharski@Sun.COM uint16_t speed;
2205*8044SWilliam.Kucharski@Sun.COM uint16_t duplex;
2206*8044SWilliam.Kucharski@Sun.COM
2207*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_config_fc_after_link_up");
2208*8044SWilliam.Kucharski@Sun.COM
2209*8044SWilliam.Kucharski@Sun.COM /* Check for the case where we have fiber media and auto-neg failed
2210*8044SWilliam.Kucharski@Sun.COM * so we had to force link. In this case, we need to force the
2211*8044SWilliam.Kucharski@Sun.COM * configuration of the MAC to match the "fc" parameter.
2212*8044SWilliam.Kucharski@Sun.COM */
2213*8044SWilliam.Kucharski@Sun.COM if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) ||
2214*8044SWilliam.Kucharski@Sun.COM ((hw->media_type == e1000_media_type_internal_serdes) && (hw->autoneg_failed))) {
2215*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_force_mac_fc(hw))) {
2216*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error forcing flow control settings\n");
2217*8044SWilliam.Kucharski@Sun.COM return ret_val;
2218*8044SWilliam.Kucharski@Sun.COM }
2219*8044SWilliam.Kucharski@Sun.COM }
2220*8044SWilliam.Kucharski@Sun.COM
2221*8044SWilliam.Kucharski@Sun.COM /* Check for the case where we have copper media and auto-neg is
2222*8044SWilliam.Kucharski@Sun.COM * enabled. In this case, we need to check and see if Auto-Neg
2223*8044SWilliam.Kucharski@Sun.COM * has completed, and if so, how the PHY and link partner has
2224*8044SWilliam.Kucharski@Sun.COM * flow control configured.
2225*8044SWilliam.Kucharski@Sun.COM */
2226*8044SWilliam.Kucharski@Sun.COM if(hw->media_type == e1000_media_type_copper) {
2227*8044SWilliam.Kucharski@Sun.COM /* Read the MII Status Register and check to see if AutoNeg
2228*8044SWilliam.Kucharski@Sun.COM * has completed. We read this twice because this reg has
2229*8044SWilliam.Kucharski@Sun.COM * some "sticky" (latched) bits.
2230*8044SWilliam.Kucharski@Sun.COM */
2231*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
2232*8044SWilliam.Kucharski@Sun.COM return ret_val;
2233*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
2234*8044SWilliam.Kucharski@Sun.COM return ret_val;
2235*8044SWilliam.Kucharski@Sun.COM
2236*8044SWilliam.Kucharski@Sun.COM if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
2237*8044SWilliam.Kucharski@Sun.COM /* The AutoNeg process has completed, so we now need to
2238*8044SWilliam.Kucharski@Sun.COM * read both the Auto Negotiation Advertisement Register
2239*8044SWilliam.Kucharski@Sun.COM * (Address 4) and the Auto_Negotiation Base Page Ability
2240*8044SWilliam.Kucharski@Sun.COM * Register (Address 5) to determine how flow control was
2241*8044SWilliam.Kucharski@Sun.COM * negotiated.
2242*8044SWilliam.Kucharski@Sun.COM */
2243*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
2244*8044SWilliam.Kucharski@Sun.COM &mii_nway_adv_reg)))
2245*8044SWilliam.Kucharski@Sun.COM return ret_val;
2246*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
2247*8044SWilliam.Kucharski@Sun.COM &mii_nway_lp_ability_reg)))
2248*8044SWilliam.Kucharski@Sun.COM return ret_val;
2249*8044SWilliam.Kucharski@Sun.COM
2250*8044SWilliam.Kucharski@Sun.COM /* Two bits in the Auto Negotiation Advertisement Register
2251*8044SWilliam.Kucharski@Sun.COM * (Address 4) and two bits in the Auto Negotiation Base
2252*8044SWilliam.Kucharski@Sun.COM * Page Ability Register (Address 5) determine flow control
2253*8044SWilliam.Kucharski@Sun.COM * for both the PHY and the link partner. The following
2254*8044SWilliam.Kucharski@Sun.COM * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
2255*8044SWilliam.Kucharski@Sun.COM * 1999, describes these PAUSE resolution bits and how flow
2256*8044SWilliam.Kucharski@Sun.COM * control is determined based upon these settings.
2257*8044SWilliam.Kucharski@Sun.COM * NOTE: DC = Don't Care
2258*8044SWilliam.Kucharski@Sun.COM *
2259*8044SWilliam.Kucharski@Sun.COM * LOCAL DEVICE | LINK PARTNER
2260*8044SWilliam.Kucharski@Sun.COM * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
2261*8044SWilliam.Kucharski@Sun.COM *-------|---------|-------|---------|--------------------
2262*8044SWilliam.Kucharski@Sun.COM * 0 | 0 | DC | DC | e1000_fc_none
2263*8044SWilliam.Kucharski@Sun.COM * 0 | 1 | 0 | DC | e1000_fc_none
2264*8044SWilliam.Kucharski@Sun.COM * 0 | 1 | 1 | 0 | e1000_fc_none
2265*8044SWilliam.Kucharski@Sun.COM * 0 | 1 | 1 | 1 | e1000_fc_tx_pause
2266*8044SWilliam.Kucharski@Sun.COM * 1 | 0 | 0 | DC | e1000_fc_none
2267*8044SWilliam.Kucharski@Sun.COM * 1 | DC | 1 | DC | e1000_fc_full
2268*8044SWilliam.Kucharski@Sun.COM * 1 | 1 | 0 | 0 | e1000_fc_none
2269*8044SWilliam.Kucharski@Sun.COM * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
2270*8044SWilliam.Kucharski@Sun.COM *
2271*8044SWilliam.Kucharski@Sun.COM */
2272*8044SWilliam.Kucharski@Sun.COM /* Are both PAUSE bits set to 1? If so, this implies
2273*8044SWilliam.Kucharski@Sun.COM * Symmetric Flow Control is enabled at both ends. The
2274*8044SWilliam.Kucharski@Sun.COM * ASM_DIR bits are irrelevant per the spec.
2275*8044SWilliam.Kucharski@Sun.COM *
2276*8044SWilliam.Kucharski@Sun.COM * For Symmetric Flow Control:
2277*8044SWilliam.Kucharski@Sun.COM *
2278*8044SWilliam.Kucharski@Sun.COM * LOCAL DEVICE | LINK PARTNER
2279*8044SWilliam.Kucharski@Sun.COM * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
2280*8044SWilliam.Kucharski@Sun.COM *-------|---------|-------|---------|--------------------
2281*8044SWilliam.Kucharski@Sun.COM * 1 | DC | 1 | DC | e1000_fc_full
2282*8044SWilliam.Kucharski@Sun.COM *
2283*8044SWilliam.Kucharski@Sun.COM */
2284*8044SWilliam.Kucharski@Sun.COM if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
2285*8044SWilliam.Kucharski@Sun.COM (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
2286*8044SWilliam.Kucharski@Sun.COM /* Now we need to check if the user selected RX ONLY
2287*8044SWilliam.Kucharski@Sun.COM * of pause frames. In this case, we had to advertise
2288*8044SWilliam.Kucharski@Sun.COM * FULL flow control because we could not advertise RX
2289*8044SWilliam.Kucharski@Sun.COM * ONLY. Hence, we must now check to see if we need to
2290*8044SWilliam.Kucharski@Sun.COM * turn OFF the TRANSMISSION of PAUSE frames.
2291*8044SWilliam.Kucharski@Sun.COM */
2292*8044SWilliam.Kucharski@Sun.COM #if 0
2293*8044SWilliam.Kucharski@Sun.COM if(hw->original_fc == e1000_fc_full) {
2294*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_full;
2295*8044SWilliam.Kucharski@Sun.COM #else
2296*8044SWilliam.Kucharski@Sun.COM if(hw->fc == e1000_fc_full) {
2297*8044SWilliam.Kucharski@Sun.COM #endif
2298*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow Control = FULL.\r\n");
2299*8044SWilliam.Kucharski@Sun.COM } else {
2300*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_rx_pause;
2301*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
2302*8044SWilliam.Kucharski@Sun.COM }
2303*8044SWilliam.Kucharski@Sun.COM }
2304*8044SWilliam.Kucharski@Sun.COM /* For receiving PAUSE frames ONLY.
2305*8044SWilliam.Kucharski@Sun.COM *
2306*8044SWilliam.Kucharski@Sun.COM * LOCAL DEVICE | LINK PARTNER
2307*8044SWilliam.Kucharski@Sun.COM * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
2308*8044SWilliam.Kucharski@Sun.COM *-------|---------|-------|---------|--------------------
2309*8044SWilliam.Kucharski@Sun.COM * 0 | 1 | 1 | 1 | e1000_fc_tx_pause
2310*8044SWilliam.Kucharski@Sun.COM *
2311*8044SWilliam.Kucharski@Sun.COM */
2312*8044SWilliam.Kucharski@Sun.COM else if(!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
2313*8044SWilliam.Kucharski@Sun.COM (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
2314*8044SWilliam.Kucharski@Sun.COM (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
2315*8044SWilliam.Kucharski@Sun.COM (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
2316*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_tx_pause;
2317*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
2318*8044SWilliam.Kucharski@Sun.COM }
2319*8044SWilliam.Kucharski@Sun.COM /* For transmitting PAUSE frames ONLY.
2320*8044SWilliam.Kucharski@Sun.COM *
2321*8044SWilliam.Kucharski@Sun.COM * LOCAL DEVICE | LINK PARTNER
2322*8044SWilliam.Kucharski@Sun.COM * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
2323*8044SWilliam.Kucharski@Sun.COM *-------|---------|-------|---------|--------------------
2324*8044SWilliam.Kucharski@Sun.COM * 1 | 1 | 0 | 1 | e1000_fc_rx_pause
2325*8044SWilliam.Kucharski@Sun.COM *
2326*8044SWilliam.Kucharski@Sun.COM */
2327*8044SWilliam.Kucharski@Sun.COM else if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
2328*8044SWilliam.Kucharski@Sun.COM (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
2329*8044SWilliam.Kucharski@Sun.COM !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
2330*8044SWilliam.Kucharski@Sun.COM (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
2331*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_rx_pause;
2332*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
2333*8044SWilliam.Kucharski@Sun.COM }
2334*8044SWilliam.Kucharski@Sun.COM /* Per the IEEE spec, at this point flow control should be
2335*8044SWilliam.Kucharski@Sun.COM * disabled. However, we want to consider that we could
2336*8044SWilliam.Kucharski@Sun.COM * be connected to a legacy switch that doesn't advertise
2337*8044SWilliam.Kucharski@Sun.COM * desired flow control, but can be forced on the link
2338*8044SWilliam.Kucharski@Sun.COM * partner. So if we advertised no flow control, that is
2339*8044SWilliam.Kucharski@Sun.COM * what we will resolve to. If we advertised some kind of
2340*8044SWilliam.Kucharski@Sun.COM * receive capability (Rx Pause Only or Full Flow Control)
2341*8044SWilliam.Kucharski@Sun.COM * and the link partner advertised none, we will configure
2342*8044SWilliam.Kucharski@Sun.COM * ourselves to enable Rx Flow Control only. We can do
2343*8044SWilliam.Kucharski@Sun.COM * this safely for two reasons: If the link partner really
2344*8044SWilliam.Kucharski@Sun.COM * didn't want flow control enabled, and we enable Rx, no
2345*8044SWilliam.Kucharski@Sun.COM * harm done since we won't be receiving any PAUSE frames
2346*8044SWilliam.Kucharski@Sun.COM * anyway. If the intent on the link partner was to have
2347*8044SWilliam.Kucharski@Sun.COM * flow control enabled, then by us enabling RX only, we
2348*8044SWilliam.Kucharski@Sun.COM * can at least receive pause frames and process them.
2349*8044SWilliam.Kucharski@Sun.COM * This is a good idea because in most cases, since we are
2350*8044SWilliam.Kucharski@Sun.COM * predominantly a server NIC, more times than not we will
2351*8044SWilliam.Kucharski@Sun.COM * be asked to delay transmission of packets than asking
2352*8044SWilliam.Kucharski@Sun.COM * our link partner to pause transmission of frames.
2353*8044SWilliam.Kucharski@Sun.COM */
2354*8044SWilliam.Kucharski@Sun.COM #if 0
2355*8044SWilliam.Kucharski@Sun.COM else if(hw->original_fc == e1000_fc_none ||
2356*8044SWilliam.Kucharski@Sun.COM hw->original_fc == e1000_fc_tx_pause) {
2357*8044SWilliam.Kucharski@Sun.COM #else
2358*8044SWilliam.Kucharski@Sun.COM else if(hw->fc == e1000_fc_none)
2359*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow Control = NONE.\r\n");
2360*8044SWilliam.Kucharski@Sun.COM else if(hw->fc == e1000_fc_tx_pause) {
2361*8044SWilliam.Kucharski@Sun.COM #endif
2362*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_none;
2363*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow Control = NONE.\r\n");
2364*8044SWilliam.Kucharski@Sun.COM } else {
2365*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_rx_pause;
2366*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
2367*8044SWilliam.Kucharski@Sun.COM }
2368*8044SWilliam.Kucharski@Sun.COM
2369*8044SWilliam.Kucharski@Sun.COM /* Now we need to do one last check... If we auto-
2370*8044SWilliam.Kucharski@Sun.COM * negotiated to HALF DUPLEX, flow control should not be
2371*8044SWilliam.Kucharski@Sun.COM * enabled per IEEE 802.3 spec.
2372*8044SWilliam.Kucharski@Sun.COM */
2373*8044SWilliam.Kucharski@Sun.COM e1000_get_speed_and_duplex(hw, &speed, &duplex);
2374*8044SWilliam.Kucharski@Sun.COM
2375*8044SWilliam.Kucharski@Sun.COM if(duplex == HALF_DUPLEX)
2376*8044SWilliam.Kucharski@Sun.COM hw->fc = e1000_fc_none;
2377*8044SWilliam.Kucharski@Sun.COM
2378*8044SWilliam.Kucharski@Sun.COM /* Now we call a subroutine to actually force the MAC
2379*8044SWilliam.Kucharski@Sun.COM * controller to use the correct flow control settings.
2380*8044SWilliam.Kucharski@Sun.COM */
2381*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_force_mac_fc(hw))) {
2382*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error forcing flow control settings\n");
2383*8044SWilliam.Kucharski@Sun.COM return ret_val;
2384*8044SWilliam.Kucharski@Sun.COM }
2385*8044SWilliam.Kucharski@Sun.COM } else {
2386*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
2387*8044SWilliam.Kucharski@Sun.COM }
2388*8044SWilliam.Kucharski@Sun.COM }
2389*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
2390*8044SWilliam.Kucharski@Sun.COM }
2391*8044SWilliam.Kucharski@Sun.COM
2392*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2393*8044SWilliam.Kucharski@Sun.COM * Checks to see if the link status of the hardware has changed.
2394*8044SWilliam.Kucharski@Sun.COM *
2395*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2396*8044SWilliam.Kucharski@Sun.COM *
2397*8044SWilliam.Kucharski@Sun.COM * Called by any function that needs to check the link status of the adapter.
2398*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
2399*8044SWilliam.Kucharski@Sun.COM static int
2400*8044SWilliam.Kucharski@Sun.COM e1000_check_for_link(struct e1000_hw *hw)
2401*8044SWilliam.Kucharski@Sun.COM {
2402*8044SWilliam.Kucharski@Sun.COM uint32_t rxcw;
2403*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl;
2404*8044SWilliam.Kucharski@Sun.COM uint32_t status;
2405*8044SWilliam.Kucharski@Sun.COM uint32_t rctl;
2406*8044SWilliam.Kucharski@Sun.COM uint32_t signal = 0;
2407*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
2408*8044SWilliam.Kucharski@Sun.COM uint16_t phy_data;
2409*8044SWilliam.Kucharski@Sun.COM uint16_t lp_capability;
2410*8044SWilliam.Kucharski@Sun.COM
2411*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_check_for_link");
2412*8044SWilliam.Kucharski@Sun.COM
2413*8044SWilliam.Kucharski@Sun.COM /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
2414*8044SWilliam.Kucharski@Sun.COM * set when the optics detect a signal. On older adapters, it will be
2415*8044SWilliam.Kucharski@Sun.COM * cleared when there is a signal. This applies to fiber media only.
2416*8044SWilliam.Kucharski@Sun.COM */
2417*8044SWilliam.Kucharski@Sun.COM if(hw->media_type == e1000_media_type_fiber)
2418*8044SWilliam.Kucharski@Sun.COM signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
2419*8044SWilliam.Kucharski@Sun.COM
2420*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
2421*8044SWilliam.Kucharski@Sun.COM status = E1000_READ_REG(hw, STATUS);
2422*8044SWilliam.Kucharski@Sun.COM rxcw = E1000_READ_REG(hw, RXCW);
2423*8044SWilliam.Kucharski@Sun.COM
2424*8044SWilliam.Kucharski@Sun.COM /* If we have a copper PHY then we only want to go out to the PHY
2425*8044SWilliam.Kucharski@Sun.COM * registers to see if Auto-Neg has completed and/or if our link
2426*8044SWilliam.Kucharski@Sun.COM * status has changed. The get_link_status flag will be set if we
2427*8044SWilliam.Kucharski@Sun.COM * receive a Link Status Change interrupt or we have Rx Sequence
2428*8044SWilliam.Kucharski@Sun.COM * Errors.
2429*8044SWilliam.Kucharski@Sun.COM */
2430*8044SWilliam.Kucharski@Sun.COM #if 0
2431*8044SWilliam.Kucharski@Sun.COM if((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
2432*8044SWilliam.Kucharski@Sun.COM #else
2433*8044SWilliam.Kucharski@Sun.COM if(hw->media_type == e1000_media_type_copper) {
2434*8044SWilliam.Kucharski@Sun.COM #endif
2435*8044SWilliam.Kucharski@Sun.COM /* First we want to see if the MII Status Register reports
2436*8044SWilliam.Kucharski@Sun.COM * link. If so, then we want to get the current speed/duplex
2437*8044SWilliam.Kucharski@Sun.COM * of the PHY.
2438*8044SWilliam.Kucharski@Sun.COM * Read the register twice since the link bit is sticky.
2439*8044SWilliam.Kucharski@Sun.COM */
2440*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
2441*8044SWilliam.Kucharski@Sun.COM return ret_val;
2442*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
2443*8044SWilliam.Kucharski@Sun.COM return ret_val;
2444*8044SWilliam.Kucharski@Sun.COM
2445*8044SWilliam.Kucharski@Sun.COM if(phy_data & MII_SR_LINK_STATUS) {
2446*8044SWilliam.Kucharski@Sun.COM #if 0
2447*8044SWilliam.Kucharski@Sun.COM hw->get_link_status = FALSE;
2448*8044SWilliam.Kucharski@Sun.COM #endif
2449*8044SWilliam.Kucharski@Sun.COM } else {
2450*8044SWilliam.Kucharski@Sun.COM /* No link detected */
2451*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_NOLINK;
2452*8044SWilliam.Kucharski@Sun.COM }
2453*8044SWilliam.Kucharski@Sun.COM
2454*8044SWilliam.Kucharski@Sun.COM /* We have a M88E1000 PHY and Auto-Neg is enabled. If we
2455*8044SWilliam.Kucharski@Sun.COM * have Si on board that is 82544 or newer, Auto
2456*8044SWilliam.Kucharski@Sun.COM * Speed Detection takes care of MAC speed/duplex
2457*8044SWilliam.Kucharski@Sun.COM * configuration. So we only need to configure Collision
2458*8044SWilliam.Kucharski@Sun.COM * Distance in the MAC. Otherwise, we need to force
2459*8044SWilliam.Kucharski@Sun.COM * speed/duplex on the MAC to the current PHY speed/duplex
2460*8044SWilliam.Kucharski@Sun.COM * settings.
2461*8044SWilliam.Kucharski@Sun.COM */
2462*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type >= e1000_82544)
2463*8044SWilliam.Kucharski@Sun.COM e1000_config_collision_dist(hw);
2464*8044SWilliam.Kucharski@Sun.COM else {
2465*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_config_mac_to_phy(hw))) {
2466*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error configuring MAC to PHY settings\n");
2467*8044SWilliam.Kucharski@Sun.COM return ret_val;
2468*8044SWilliam.Kucharski@Sun.COM }
2469*8044SWilliam.Kucharski@Sun.COM }
2470*8044SWilliam.Kucharski@Sun.COM
2471*8044SWilliam.Kucharski@Sun.COM /* Configure Flow Control now that Auto-Neg has completed. First, we
2472*8044SWilliam.Kucharski@Sun.COM * need to restore the desired flow control settings because we may
2473*8044SWilliam.Kucharski@Sun.COM * have had to re-autoneg with a different link partner.
2474*8044SWilliam.Kucharski@Sun.COM */
2475*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_config_fc_after_link_up(hw))) {
2476*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error configuring flow control\n");
2477*8044SWilliam.Kucharski@Sun.COM return ret_val;
2478*8044SWilliam.Kucharski@Sun.COM }
2479*8044SWilliam.Kucharski@Sun.COM
2480*8044SWilliam.Kucharski@Sun.COM /* At this point we know that we are on copper and we have
2481*8044SWilliam.Kucharski@Sun.COM * auto-negotiated link. These are conditions for checking the link
2482*8044SWilliam.Kucharski@Sun.COM * parter capability register. We use the link partner capability to
2483*8044SWilliam.Kucharski@Sun.COM * determine if TBI Compatibility needs to be turned on or off. If
2484*8044SWilliam.Kucharski@Sun.COM * the link partner advertises any speed in addition to Gigabit, then
2485*8044SWilliam.Kucharski@Sun.COM * we assume that they are GMII-based, and TBI compatibility is not
2486*8044SWilliam.Kucharski@Sun.COM * needed. If no other speeds are advertised, we assume the link
2487*8044SWilliam.Kucharski@Sun.COM * partner is TBI-based, and we turn on TBI Compatibility.
2488*8044SWilliam.Kucharski@Sun.COM */
2489*8044SWilliam.Kucharski@Sun.COM if(hw->tbi_compatibility_en) {
2490*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
2491*8044SWilliam.Kucharski@Sun.COM &lp_capability)))
2492*8044SWilliam.Kucharski@Sun.COM return ret_val;
2493*8044SWilliam.Kucharski@Sun.COM if(lp_capability & (NWAY_LPAR_10T_HD_CAPS |
2494*8044SWilliam.Kucharski@Sun.COM NWAY_LPAR_10T_FD_CAPS |
2495*8044SWilliam.Kucharski@Sun.COM NWAY_LPAR_100TX_HD_CAPS |
2496*8044SWilliam.Kucharski@Sun.COM NWAY_LPAR_100TX_FD_CAPS |
2497*8044SWilliam.Kucharski@Sun.COM NWAY_LPAR_100T4_CAPS)) {
2498*8044SWilliam.Kucharski@Sun.COM /* If our link partner advertises anything in addition to
2499*8044SWilliam.Kucharski@Sun.COM * gigabit, we do not need to enable TBI compatibility.
2500*8044SWilliam.Kucharski@Sun.COM */
2501*8044SWilliam.Kucharski@Sun.COM if(hw->tbi_compatibility_on) {
2502*8044SWilliam.Kucharski@Sun.COM /* If we previously were in the mode, turn it off. */
2503*8044SWilliam.Kucharski@Sun.COM rctl = E1000_READ_REG(hw, RCTL);
2504*8044SWilliam.Kucharski@Sun.COM rctl &= ~E1000_RCTL_SBP;
2505*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, RCTL, rctl);
2506*8044SWilliam.Kucharski@Sun.COM hw->tbi_compatibility_on = FALSE;
2507*8044SWilliam.Kucharski@Sun.COM }
2508*8044SWilliam.Kucharski@Sun.COM } else {
2509*8044SWilliam.Kucharski@Sun.COM /* If TBI compatibility is was previously off, turn it on. For
2510*8044SWilliam.Kucharski@Sun.COM * compatibility with a TBI link partner, we will store bad
2511*8044SWilliam.Kucharski@Sun.COM * packets. Some frames have an additional byte on the end and
2512*8044SWilliam.Kucharski@Sun.COM * will look like CRC errors to to the hardware.
2513*8044SWilliam.Kucharski@Sun.COM */
2514*8044SWilliam.Kucharski@Sun.COM if(!hw->tbi_compatibility_on) {
2515*8044SWilliam.Kucharski@Sun.COM hw->tbi_compatibility_on = TRUE;
2516*8044SWilliam.Kucharski@Sun.COM rctl = E1000_READ_REG(hw, RCTL);
2517*8044SWilliam.Kucharski@Sun.COM rctl |= E1000_RCTL_SBP;
2518*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, RCTL, rctl);
2519*8044SWilliam.Kucharski@Sun.COM }
2520*8044SWilliam.Kucharski@Sun.COM }
2521*8044SWilliam.Kucharski@Sun.COM }
2522*8044SWilliam.Kucharski@Sun.COM }
2523*8044SWilliam.Kucharski@Sun.COM /* If we don't have link (auto-negotiation failed or link partner cannot
2524*8044SWilliam.Kucharski@Sun.COM * auto-negotiate), the cable is plugged in (we have signal), and our
2525*8044SWilliam.Kucharski@Sun.COM * link partner is not trying to auto-negotiate with us (we are receiving
2526*8044SWilliam.Kucharski@Sun.COM * idles or data), we need to force link up. We also need to give
2527*8044SWilliam.Kucharski@Sun.COM * auto-negotiation time to complete, in case the cable was just plugged
2528*8044SWilliam.Kucharski@Sun.COM * in. The autoneg_failed flag does this.
2529*8044SWilliam.Kucharski@Sun.COM */
2530*8044SWilliam.Kucharski@Sun.COM else if((((hw->media_type == e1000_media_type_fiber) &&
2531*8044SWilliam.Kucharski@Sun.COM ((ctrl & E1000_CTRL_SWDPIN1) == signal)) ||
2532*8044SWilliam.Kucharski@Sun.COM (hw->media_type == e1000_media_type_internal_serdes)) &&
2533*8044SWilliam.Kucharski@Sun.COM (!(status & E1000_STATUS_LU)) &&
2534*8044SWilliam.Kucharski@Sun.COM (!(rxcw & E1000_RXCW_C))) {
2535*8044SWilliam.Kucharski@Sun.COM if(hw->autoneg_failed == 0) {
2536*8044SWilliam.Kucharski@Sun.COM hw->autoneg_failed = 1;
2537*8044SWilliam.Kucharski@Sun.COM return 0;
2538*8044SWilliam.Kucharski@Sun.COM }
2539*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
2540*8044SWilliam.Kucharski@Sun.COM
2541*8044SWilliam.Kucharski@Sun.COM /* Disable auto-negotiation in the TXCW register */
2542*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
2543*8044SWilliam.Kucharski@Sun.COM
2544*8044SWilliam.Kucharski@Sun.COM /* Force link-up and also force full-duplex. */
2545*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
2546*8044SWilliam.Kucharski@Sun.COM ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
2547*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
2548*8044SWilliam.Kucharski@Sun.COM
2549*8044SWilliam.Kucharski@Sun.COM /* Configure Flow Control after forcing link up. */
2550*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_config_fc_after_link_up(hw))) {
2551*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Error configuring flow control\n");
2552*8044SWilliam.Kucharski@Sun.COM return ret_val;
2553*8044SWilliam.Kucharski@Sun.COM }
2554*8044SWilliam.Kucharski@Sun.COM }
2555*8044SWilliam.Kucharski@Sun.COM /* If we are forcing link and we are receiving /C/ ordered sets, re-enable
2556*8044SWilliam.Kucharski@Sun.COM * auto-negotiation in the TXCW register and disable forced link in the
2557*8044SWilliam.Kucharski@Sun.COM * Device Control register in an attempt to auto-negotiate with our link
2558*8044SWilliam.Kucharski@Sun.COM * partner.
2559*8044SWilliam.Kucharski@Sun.COM */
2560*8044SWilliam.Kucharski@Sun.COM else if(((hw->media_type == e1000_media_type_fiber) ||
2561*8044SWilliam.Kucharski@Sun.COM (hw->media_type == e1000_media_type_internal_serdes)) &&
2562*8044SWilliam.Kucharski@Sun.COM (ctrl & E1000_CTRL_SLU) &&
2563*8044SWilliam.Kucharski@Sun.COM (rxcw & E1000_RXCW_C)) {
2564*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
2565*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, TXCW, hw->txcw);
2566*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
2567*8044SWilliam.Kucharski@Sun.COM }
2568*8044SWilliam.Kucharski@Sun.COM #if 0
2569*8044SWilliam.Kucharski@Sun.COM /* If we force link for non-auto-negotiation switch, check link status
2570*8044SWilliam.Kucharski@Sun.COM * based on MAC synchronization for internal serdes media type.
2571*8044SWilliam.Kucharski@Sun.COM */
2572*8044SWilliam.Kucharski@Sun.COM else if((hw->media_type == e1000_media_type_internal_serdes) &&
2573*8044SWilliam.Kucharski@Sun.COM !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
2574*8044SWilliam.Kucharski@Sun.COM /* SYNCH bit and IV bit are sticky. */
2575*8044SWilliam.Kucharski@Sun.COM udelay(10);
2576*8044SWilliam.Kucharski@Sun.COM if(E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
2577*8044SWilliam.Kucharski@Sun.COM if(!(rxcw & E1000_RXCW_IV)) {
2578*8044SWilliam.Kucharski@Sun.COM hw->serdes_link_down = FALSE;
2579*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("SERDES: Link is up.\n");
2580*8044SWilliam.Kucharski@Sun.COM }
2581*8044SWilliam.Kucharski@Sun.COM } else {
2582*8044SWilliam.Kucharski@Sun.COM hw->serdes_link_down = TRUE;
2583*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("SERDES: Link is down.\n");
2584*8044SWilliam.Kucharski@Sun.COM }
2585*8044SWilliam.Kucharski@Sun.COM }
2586*8044SWilliam.Kucharski@Sun.COM #endif
2587*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
2588*8044SWilliam.Kucharski@Sun.COM }
2589*8044SWilliam.Kucharski@Sun.COM
2590*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2591*8044SWilliam.Kucharski@Sun.COM * Detects the current speed and duplex settings of the hardware.
2592*8044SWilliam.Kucharski@Sun.COM *
2593*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2594*8044SWilliam.Kucharski@Sun.COM * speed - Speed of the connection
2595*8044SWilliam.Kucharski@Sun.COM * duplex - Duplex setting of the connection
2596*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
2597*8044SWilliam.Kucharski@Sun.COM static void
2598*8044SWilliam.Kucharski@Sun.COM e1000_get_speed_and_duplex(struct e1000_hw *hw,
2599*8044SWilliam.Kucharski@Sun.COM uint16_t *speed,
2600*8044SWilliam.Kucharski@Sun.COM uint16_t *duplex)
2601*8044SWilliam.Kucharski@Sun.COM {
2602*8044SWilliam.Kucharski@Sun.COM uint32_t status;
2603*8044SWilliam.Kucharski@Sun.COM
2604*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_get_speed_and_duplex");
2605*8044SWilliam.Kucharski@Sun.COM
2606*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type >= e1000_82543) {
2607*8044SWilliam.Kucharski@Sun.COM status = E1000_READ_REG(hw, STATUS);
2608*8044SWilliam.Kucharski@Sun.COM if(status & E1000_STATUS_SPEED_1000) {
2609*8044SWilliam.Kucharski@Sun.COM *speed = SPEED_1000;
2610*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("1000 Mbs, ");
2611*8044SWilliam.Kucharski@Sun.COM } else if(status & E1000_STATUS_SPEED_100) {
2612*8044SWilliam.Kucharski@Sun.COM *speed = SPEED_100;
2613*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("100 Mbs, ");
2614*8044SWilliam.Kucharski@Sun.COM } else {
2615*8044SWilliam.Kucharski@Sun.COM *speed = SPEED_10;
2616*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("10 Mbs, ");
2617*8044SWilliam.Kucharski@Sun.COM }
2618*8044SWilliam.Kucharski@Sun.COM
2619*8044SWilliam.Kucharski@Sun.COM if(status & E1000_STATUS_FD) {
2620*8044SWilliam.Kucharski@Sun.COM *duplex = FULL_DUPLEX;
2621*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Full Duplex\r\n");
2622*8044SWilliam.Kucharski@Sun.COM } else {
2623*8044SWilliam.Kucharski@Sun.COM *duplex = HALF_DUPLEX;
2624*8044SWilliam.Kucharski@Sun.COM DEBUGOUT(" Half Duplex\r\n");
2625*8044SWilliam.Kucharski@Sun.COM }
2626*8044SWilliam.Kucharski@Sun.COM } else {
2627*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("1000 Mbs, Full Duplex\r\n");
2628*8044SWilliam.Kucharski@Sun.COM *speed = SPEED_1000;
2629*8044SWilliam.Kucharski@Sun.COM *duplex = FULL_DUPLEX;
2630*8044SWilliam.Kucharski@Sun.COM }
2631*8044SWilliam.Kucharski@Sun.COM }
2632*8044SWilliam.Kucharski@Sun.COM
2633*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2634*8044SWilliam.Kucharski@Sun.COM * Blocks until autoneg completes or times out (~4.5 seconds)
2635*8044SWilliam.Kucharski@Sun.COM *
2636*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2637*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2638*8044SWilliam.Kucharski@Sun.COM static int
2639*8044SWilliam.Kucharski@Sun.COM e1000_wait_autoneg(struct e1000_hw *hw)
2640*8044SWilliam.Kucharski@Sun.COM {
2641*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
2642*8044SWilliam.Kucharski@Sun.COM uint16_t i;
2643*8044SWilliam.Kucharski@Sun.COM uint16_t phy_data;
2644*8044SWilliam.Kucharski@Sun.COM
2645*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_wait_autoneg");
2646*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Waiting for Auto-Neg to complete.\n");
2647*8044SWilliam.Kucharski@Sun.COM
2648*8044SWilliam.Kucharski@Sun.COM /* We will wait for autoneg to complete or 4.5 seconds to expire. */
2649*8044SWilliam.Kucharski@Sun.COM for(i = PHY_AUTO_NEG_TIME; i > 0; i--) {
2650*8044SWilliam.Kucharski@Sun.COM /* Read the MII Status Register and wait for Auto-Neg
2651*8044SWilliam.Kucharski@Sun.COM * Complete bit to be set.
2652*8044SWilliam.Kucharski@Sun.COM */
2653*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
2654*8044SWilliam.Kucharski@Sun.COM return ret_val;
2655*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
2656*8044SWilliam.Kucharski@Sun.COM return ret_val;
2657*8044SWilliam.Kucharski@Sun.COM if(phy_data & MII_SR_AUTONEG_COMPLETE) {
2658*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Auto-Neg complete.\n");
2659*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
2660*8044SWilliam.Kucharski@Sun.COM }
2661*8044SWilliam.Kucharski@Sun.COM mdelay(100);
2662*8044SWilliam.Kucharski@Sun.COM }
2663*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Auto-Neg timedout.\n");
2664*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_TIMEOUT;
2665*8044SWilliam.Kucharski@Sun.COM }
2666*8044SWilliam.Kucharski@Sun.COM
2667*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2668*8044SWilliam.Kucharski@Sun.COM * Raises the Management Data Clock
2669*8044SWilliam.Kucharski@Sun.COM *
2670*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2671*8044SWilliam.Kucharski@Sun.COM * ctrl - Device control register's current value
2672*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2673*8044SWilliam.Kucharski@Sun.COM static void
2674*8044SWilliam.Kucharski@Sun.COM e1000_raise_mdi_clk(struct e1000_hw *hw,
2675*8044SWilliam.Kucharski@Sun.COM uint32_t *ctrl)
2676*8044SWilliam.Kucharski@Sun.COM {
2677*8044SWilliam.Kucharski@Sun.COM /* Raise the clock input to the Management Data Clock (by setting the MDC
2678*8044SWilliam.Kucharski@Sun.COM * bit), and then delay 10 microseconds.
2679*8044SWilliam.Kucharski@Sun.COM */
2680*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC));
2681*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
2682*8044SWilliam.Kucharski@Sun.COM udelay(10);
2683*8044SWilliam.Kucharski@Sun.COM }
2684*8044SWilliam.Kucharski@Sun.COM
2685*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2686*8044SWilliam.Kucharski@Sun.COM * Lowers the Management Data Clock
2687*8044SWilliam.Kucharski@Sun.COM *
2688*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2689*8044SWilliam.Kucharski@Sun.COM * ctrl - Device control register's current value
2690*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2691*8044SWilliam.Kucharski@Sun.COM static void
2692*8044SWilliam.Kucharski@Sun.COM e1000_lower_mdi_clk(struct e1000_hw *hw,
2693*8044SWilliam.Kucharski@Sun.COM uint32_t *ctrl)
2694*8044SWilliam.Kucharski@Sun.COM {
2695*8044SWilliam.Kucharski@Sun.COM /* Lower the clock input to the Management Data Clock (by clearing the MDC
2696*8044SWilliam.Kucharski@Sun.COM * bit), and then delay 10 microseconds.
2697*8044SWilliam.Kucharski@Sun.COM */
2698*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC));
2699*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
2700*8044SWilliam.Kucharski@Sun.COM udelay(10);
2701*8044SWilliam.Kucharski@Sun.COM }
2702*8044SWilliam.Kucharski@Sun.COM
2703*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2704*8044SWilliam.Kucharski@Sun.COM * Shifts data bits out to the PHY
2705*8044SWilliam.Kucharski@Sun.COM *
2706*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2707*8044SWilliam.Kucharski@Sun.COM * data - Data to send out to the PHY
2708*8044SWilliam.Kucharski@Sun.COM * count - Number of bits to shift out
2709*8044SWilliam.Kucharski@Sun.COM *
2710*8044SWilliam.Kucharski@Sun.COM * Bits are shifted out in MSB to LSB order.
2711*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2712*8044SWilliam.Kucharski@Sun.COM static void
2713*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_mdi_bits(struct e1000_hw *hw,
2714*8044SWilliam.Kucharski@Sun.COM uint32_t data,
2715*8044SWilliam.Kucharski@Sun.COM uint16_t count)
2716*8044SWilliam.Kucharski@Sun.COM {
2717*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl;
2718*8044SWilliam.Kucharski@Sun.COM uint32_t mask;
2719*8044SWilliam.Kucharski@Sun.COM
2720*8044SWilliam.Kucharski@Sun.COM /* We need to shift "count" number of bits out to the PHY. So, the value
2721*8044SWilliam.Kucharski@Sun.COM * in the "data" parameter will be shifted out to the PHY one bit at a
2722*8044SWilliam.Kucharski@Sun.COM * time. In order to do this, "data" must be broken down into bits.
2723*8044SWilliam.Kucharski@Sun.COM */
2724*8044SWilliam.Kucharski@Sun.COM mask = 0x01;
2725*8044SWilliam.Kucharski@Sun.COM mask <<= (count - 1);
2726*8044SWilliam.Kucharski@Sun.COM
2727*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
2728*8044SWilliam.Kucharski@Sun.COM
2729*8044SWilliam.Kucharski@Sun.COM /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
2730*8044SWilliam.Kucharski@Sun.COM ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
2731*8044SWilliam.Kucharski@Sun.COM
2732*8044SWilliam.Kucharski@Sun.COM while(mask) {
2733*8044SWilliam.Kucharski@Sun.COM /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and
2734*8044SWilliam.Kucharski@Sun.COM * then raising and lowering the Management Data Clock. A "0" is
2735*8044SWilliam.Kucharski@Sun.COM * shifted out to the PHY by setting the MDIO bit to "0" and then
2736*8044SWilliam.Kucharski@Sun.COM * raising and lowering the clock.
2737*8044SWilliam.Kucharski@Sun.COM */
2738*8044SWilliam.Kucharski@Sun.COM if(data & mask) ctrl |= E1000_CTRL_MDIO;
2739*8044SWilliam.Kucharski@Sun.COM else ctrl &= ~E1000_CTRL_MDIO;
2740*8044SWilliam.Kucharski@Sun.COM
2741*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
2742*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
2743*8044SWilliam.Kucharski@Sun.COM
2744*8044SWilliam.Kucharski@Sun.COM udelay(10);
2745*8044SWilliam.Kucharski@Sun.COM
2746*8044SWilliam.Kucharski@Sun.COM e1000_raise_mdi_clk(hw, &ctrl);
2747*8044SWilliam.Kucharski@Sun.COM e1000_lower_mdi_clk(hw, &ctrl);
2748*8044SWilliam.Kucharski@Sun.COM
2749*8044SWilliam.Kucharski@Sun.COM mask = mask >> 1;
2750*8044SWilliam.Kucharski@Sun.COM }
2751*8044SWilliam.Kucharski@Sun.COM }
2752*8044SWilliam.Kucharski@Sun.COM
2753*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2754*8044SWilliam.Kucharski@Sun.COM * Shifts data bits in from the PHY
2755*8044SWilliam.Kucharski@Sun.COM *
2756*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2757*8044SWilliam.Kucharski@Sun.COM *
2758*8044SWilliam.Kucharski@Sun.COM * Bits are shifted in in MSB to LSB order.
2759*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2760*8044SWilliam.Kucharski@Sun.COM static uint16_t
2761*8044SWilliam.Kucharski@Sun.COM e1000_shift_in_mdi_bits(struct e1000_hw *hw)
2762*8044SWilliam.Kucharski@Sun.COM {
2763*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl;
2764*8044SWilliam.Kucharski@Sun.COM uint16_t data = 0;
2765*8044SWilliam.Kucharski@Sun.COM uint8_t i;
2766*8044SWilliam.Kucharski@Sun.COM
2767*8044SWilliam.Kucharski@Sun.COM /* In order to read a register from the PHY, we need to shift in a total
2768*8044SWilliam.Kucharski@Sun.COM * of 18 bits from the PHY. The first two bit (turnaround) times are used
2769*8044SWilliam.Kucharski@Sun.COM * to avoid contention on the MDIO pin when a read operation is performed.
2770*8044SWilliam.Kucharski@Sun.COM * These two bits are ignored by us and thrown away. Bits are "shifted in"
2771*8044SWilliam.Kucharski@Sun.COM * by raising the input to the Management Data Clock (setting the MDC bit),
2772*8044SWilliam.Kucharski@Sun.COM * and then reading the value of the MDIO bit.
2773*8044SWilliam.Kucharski@Sun.COM */
2774*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
2775*8044SWilliam.Kucharski@Sun.COM
2776*8044SWilliam.Kucharski@Sun.COM /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
2777*8044SWilliam.Kucharski@Sun.COM ctrl &= ~E1000_CTRL_MDIO_DIR;
2778*8044SWilliam.Kucharski@Sun.COM ctrl &= ~E1000_CTRL_MDIO;
2779*8044SWilliam.Kucharski@Sun.COM
2780*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
2781*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
2782*8044SWilliam.Kucharski@Sun.COM
2783*8044SWilliam.Kucharski@Sun.COM /* Raise and Lower the clock before reading in the data. This accounts for
2784*8044SWilliam.Kucharski@Sun.COM * the turnaround bits. The first clock occurred when we clocked out the
2785*8044SWilliam.Kucharski@Sun.COM * last bit of the Register Address.
2786*8044SWilliam.Kucharski@Sun.COM */
2787*8044SWilliam.Kucharski@Sun.COM e1000_raise_mdi_clk(hw, &ctrl);
2788*8044SWilliam.Kucharski@Sun.COM e1000_lower_mdi_clk(hw, &ctrl);
2789*8044SWilliam.Kucharski@Sun.COM
2790*8044SWilliam.Kucharski@Sun.COM for(data = 0, i = 0; i < 16; i++) {
2791*8044SWilliam.Kucharski@Sun.COM data = data << 1;
2792*8044SWilliam.Kucharski@Sun.COM e1000_raise_mdi_clk(hw, &ctrl);
2793*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
2794*8044SWilliam.Kucharski@Sun.COM /* Check to see if we shifted in a "1". */
2795*8044SWilliam.Kucharski@Sun.COM if(ctrl & E1000_CTRL_MDIO) data |= 1;
2796*8044SWilliam.Kucharski@Sun.COM e1000_lower_mdi_clk(hw, &ctrl);
2797*8044SWilliam.Kucharski@Sun.COM }
2798*8044SWilliam.Kucharski@Sun.COM
2799*8044SWilliam.Kucharski@Sun.COM e1000_raise_mdi_clk(hw, &ctrl);
2800*8044SWilliam.Kucharski@Sun.COM e1000_lower_mdi_clk(hw, &ctrl);
2801*8044SWilliam.Kucharski@Sun.COM
2802*8044SWilliam.Kucharski@Sun.COM return data;
2803*8044SWilliam.Kucharski@Sun.COM }
2804*8044SWilliam.Kucharski@Sun.COM
2805*8044SWilliam.Kucharski@Sun.COM /*****************************************************************************
2806*8044SWilliam.Kucharski@Sun.COM * Reads the value from a PHY register, if the value is on a specific non zero
2807*8044SWilliam.Kucharski@Sun.COM * page, sets the page first.
2808*8044SWilliam.Kucharski@Sun.COM *
2809*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2810*8044SWilliam.Kucharski@Sun.COM * reg_addr - address of the PHY register to read
2811*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2812*8044SWilliam.Kucharski@Sun.COM static int
2813*8044SWilliam.Kucharski@Sun.COM e1000_read_phy_reg(struct e1000_hw *hw,
2814*8044SWilliam.Kucharski@Sun.COM uint32_t reg_addr,
2815*8044SWilliam.Kucharski@Sun.COM uint16_t *phy_data)
2816*8044SWilliam.Kucharski@Sun.COM {
2817*8044SWilliam.Kucharski@Sun.COM uint32_t ret_val;
2818*8044SWilliam.Kucharski@Sun.COM
2819*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_read_phy_reg");
2820*8044SWilliam.Kucharski@Sun.COM
2821*8044SWilliam.Kucharski@Sun.COM if(hw->phy_type == e1000_phy_igp &&
2822*8044SWilliam.Kucharski@Sun.COM (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
2823*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
2824*8044SWilliam.Kucharski@Sun.COM (uint16_t)reg_addr)))
2825*8044SWilliam.Kucharski@Sun.COM return ret_val;
2826*8044SWilliam.Kucharski@Sun.COM }
2827*8044SWilliam.Kucharski@Sun.COM
2828*8044SWilliam.Kucharski@Sun.COM ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
2829*8044SWilliam.Kucharski@Sun.COM phy_data);
2830*8044SWilliam.Kucharski@Sun.COM
2831*8044SWilliam.Kucharski@Sun.COM return ret_val;
2832*8044SWilliam.Kucharski@Sun.COM }
2833*8044SWilliam.Kucharski@Sun.COM
2834*8044SWilliam.Kucharski@Sun.COM static int
2835*8044SWilliam.Kucharski@Sun.COM e1000_read_phy_reg_ex(struct e1000_hw *hw,
2836*8044SWilliam.Kucharski@Sun.COM uint32_t reg_addr,
2837*8044SWilliam.Kucharski@Sun.COM uint16_t *phy_data)
2838*8044SWilliam.Kucharski@Sun.COM {
2839*8044SWilliam.Kucharski@Sun.COM uint32_t i;
2840*8044SWilliam.Kucharski@Sun.COM uint32_t mdic = 0;
2841*8044SWilliam.Kucharski@Sun.COM const uint32_t phy_addr = 1;
2842*8044SWilliam.Kucharski@Sun.COM
2843*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_read_phy_reg_ex");
2844*8044SWilliam.Kucharski@Sun.COM
2845*8044SWilliam.Kucharski@Sun.COM if(reg_addr > MAX_PHY_REG_ADDRESS) {
2846*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
2847*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_PARAM;
2848*8044SWilliam.Kucharski@Sun.COM }
2849*8044SWilliam.Kucharski@Sun.COM
2850*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type > e1000_82543) {
2851*8044SWilliam.Kucharski@Sun.COM /* Set up Op-code, Phy Address, and register address in the MDI
2852*8044SWilliam.Kucharski@Sun.COM * Control register. The MAC will take care of interfacing with the
2853*8044SWilliam.Kucharski@Sun.COM * PHY to retrieve the desired data.
2854*8044SWilliam.Kucharski@Sun.COM */
2855*8044SWilliam.Kucharski@Sun.COM mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
2856*8044SWilliam.Kucharski@Sun.COM (phy_addr << E1000_MDIC_PHY_SHIFT) |
2857*8044SWilliam.Kucharski@Sun.COM (E1000_MDIC_OP_READ));
2858*8044SWilliam.Kucharski@Sun.COM
2859*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, MDIC, mdic);
2860*8044SWilliam.Kucharski@Sun.COM
2861*8044SWilliam.Kucharski@Sun.COM /* Poll the ready bit to see if the MDI read completed */
2862*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < 64; i++) {
2863*8044SWilliam.Kucharski@Sun.COM udelay(50);
2864*8044SWilliam.Kucharski@Sun.COM mdic = E1000_READ_REG(hw, MDIC);
2865*8044SWilliam.Kucharski@Sun.COM if(mdic & E1000_MDIC_READY) break;
2866*8044SWilliam.Kucharski@Sun.COM }
2867*8044SWilliam.Kucharski@Sun.COM if(!(mdic & E1000_MDIC_READY)) {
2868*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("MDI Read did not complete\n");
2869*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_PHY;
2870*8044SWilliam.Kucharski@Sun.COM }
2871*8044SWilliam.Kucharski@Sun.COM if(mdic & E1000_MDIC_ERROR) {
2872*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("MDI Error\n");
2873*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_PHY;
2874*8044SWilliam.Kucharski@Sun.COM }
2875*8044SWilliam.Kucharski@Sun.COM *phy_data = (uint16_t) mdic;
2876*8044SWilliam.Kucharski@Sun.COM } else {
2877*8044SWilliam.Kucharski@Sun.COM /* We must first send a preamble through the MDIO pin to signal the
2878*8044SWilliam.Kucharski@Sun.COM * beginning of an MII instruction. This is done by sending 32
2879*8044SWilliam.Kucharski@Sun.COM * consecutive "1" bits.
2880*8044SWilliam.Kucharski@Sun.COM */
2881*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
2882*8044SWilliam.Kucharski@Sun.COM
2883*8044SWilliam.Kucharski@Sun.COM /* Now combine the next few fields that are required for a read
2884*8044SWilliam.Kucharski@Sun.COM * operation. We use this method instead of calling the
2885*8044SWilliam.Kucharski@Sun.COM * e1000_shift_out_mdi_bits routine five different times. The format of
2886*8044SWilliam.Kucharski@Sun.COM * a MII read instruction consists of a shift out of 14 bits and is
2887*8044SWilliam.Kucharski@Sun.COM * defined as follows:
2888*8044SWilliam.Kucharski@Sun.COM * <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
2889*8044SWilliam.Kucharski@Sun.COM * followed by a shift in of 18 bits. This first two bits shifted in
2890*8044SWilliam.Kucharski@Sun.COM * are TurnAround bits used to avoid contention on the MDIO pin when a
2891*8044SWilliam.Kucharski@Sun.COM * READ operation is performed. These two bits are thrown away
2892*8044SWilliam.Kucharski@Sun.COM * followed by a shift in of 16 bits which contains the desired data.
2893*8044SWilliam.Kucharski@Sun.COM */
2894*8044SWilliam.Kucharski@Sun.COM mdic = ((reg_addr) | (phy_addr << 5) |
2895*8044SWilliam.Kucharski@Sun.COM (PHY_OP_READ << 10) | (PHY_SOF << 12));
2896*8044SWilliam.Kucharski@Sun.COM
2897*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_mdi_bits(hw, mdic, 14);
2898*8044SWilliam.Kucharski@Sun.COM
2899*8044SWilliam.Kucharski@Sun.COM /* Now that we've shifted out the read command to the MII, we need to
2900*8044SWilliam.Kucharski@Sun.COM * "shift in" the 16-bit value (18 total bits) of the requested PHY
2901*8044SWilliam.Kucharski@Sun.COM * register address.
2902*8044SWilliam.Kucharski@Sun.COM */
2903*8044SWilliam.Kucharski@Sun.COM *phy_data = e1000_shift_in_mdi_bits(hw);
2904*8044SWilliam.Kucharski@Sun.COM }
2905*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
2906*8044SWilliam.Kucharski@Sun.COM }
2907*8044SWilliam.Kucharski@Sun.COM
2908*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
2909*8044SWilliam.Kucharski@Sun.COM * Writes a value to a PHY register
2910*8044SWilliam.Kucharski@Sun.COM *
2911*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
2912*8044SWilliam.Kucharski@Sun.COM * reg_addr - address of the PHY register to write
2913*8044SWilliam.Kucharski@Sun.COM * data - data to write to the PHY
2914*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
2915*8044SWilliam.Kucharski@Sun.COM static int
2916*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg(struct e1000_hw *hw,
2917*8044SWilliam.Kucharski@Sun.COM uint32_t reg_addr,
2918*8044SWilliam.Kucharski@Sun.COM uint16_t phy_data)
2919*8044SWilliam.Kucharski@Sun.COM {
2920*8044SWilliam.Kucharski@Sun.COM uint32_t ret_val;
2921*8044SWilliam.Kucharski@Sun.COM
2922*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_write_phy_reg");
2923*8044SWilliam.Kucharski@Sun.COM
2924*8044SWilliam.Kucharski@Sun.COM if(hw->phy_type == e1000_phy_igp &&
2925*8044SWilliam.Kucharski@Sun.COM (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
2926*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
2927*8044SWilliam.Kucharski@Sun.COM (uint16_t)reg_addr)))
2928*8044SWilliam.Kucharski@Sun.COM return ret_val;
2929*8044SWilliam.Kucharski@Sun.COM }
2930*8044SWilliam.Kucharski@Sun.COM
2931*8044SWilliam.Kucharski@Sun.COM ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
2932*8044SWilliam.Kucharski@Sun.COM phy_data);
2933*8044SWilliam.Kucharski@Sun.COM
2934*8044SWilliam.Kucharski@Sun.COM return ret_val;
2935*8044SWilliam.Kucharski@Sun.COM }
2936*8044SWilliam.Kucharski@Sun.COM
2937*8044SWilliam.Kucharski@Sun.COM static int
2938*8044SWilliam.Kucharski@Sun.COM e1000_write_phy_reg_ex(struct e1000_hw *hw,
2939*8044SWilliam.Kucharski@Sun.COM uint32_t reg_addr,
2940*8044SWilliam.Kucharski@Sun.COM uint16_t phy_data)
2941*8044SWilliam.Kucharski@Sun.COM {
2942*8044SWilliam.Kucharski@Sun.COM uint32_t i;
2943*8044SWilliam.Kucharski@Sun.COM uint32_t mdic = 0;
2944*8044SWilliam.Kucharski@Sun.COM const uint32_t phy_addr = 1;
2945*8044SWilliam.Kucharski@Sun.COM
2946*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_write_phy_reg_ex");
2947*8044SWilliam.Kucharski@Sun.COM
2948*8044SWilliam.Kucharski@Sun.COM if(reg_addr > MAX_PHY_REG_ADDRESS) {
2949*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
2950*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_PARAM;
2951*8044SWilliam.Kucharski@Sun.COM }
2952*8044SWilliam.Kucharski@Sun.COM
2953*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type > e1000_82543) {
2954*8044SWilliam.Kucharski@Sun.COM /* Set up Op-code, Phy Address, register address, and data intended
2955*8044SWilliam.Kucharski@Sun.COM * for the PHY register in the MDI Control register. The MAC will take
2956*8044SWilliam.Kucharski@Sun.COM * care of interfacing with the PHY to send the desired data.
2957*8044SWilliam.Kucharski@Sun.COM */
2958*8044SWilliam.Kucharski@Sun.COM mdic = (((uint32_t) phy_data) |
2959*8044SWilliam.Kucharski@Sun.COM (reg_addr << E1000_MDIC_REG_SHIFT) |
2960*8044SWilliam.Kucharski@Sun.COM (phy_addr << E1000_MDIC_PHY_SHIFT) |
2961*8044SWilliam.Kucharski@Sun.COM (E1000_MDIC_OP_WRITE));
2962*8044SWilliam.Kucharski@Sun.COM
2963*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, MDIC, mdic);
2964*8044SWilliam.Kucharski@Sun.COM
2965*8044SWilliam.Kucharski@Sun.COM /* Poll the ready bit to see if the MDI read completed */
2966*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < 640; i++) {
2967*8044SWilliam.Kucharski@Sun.COM udelay(5);
2968*8044SWilliam.Kucharski@Sun.COM mdic = E1000_READ_REG(hw, MDIC);
2969*8044SWilliam.Kucharski@Sun.COM if(mdic & E1000_MDIC_READY) break;
2970*8044SWilliam.Kucharski@Sun.COM }
2971*8044SWilliam.Kucharski@Sun.COM if(!(mdic & E1000_MDIC_READY)) {
2972*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("MDI Write did not complete\n");
2973*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_PHY;
2974*8044SWilliam.Kucharski@Sun.COM }
2975*8044SWilliam.Kucharski@Sun.COM } else {
2976*8044SWilliam.Kucharski@Sun.COM /* We'll need to use the SW defined pins to shift the write command
2977*8044SWilliam.Kucharski@Sun.COM * out to the PHY. We first send a preamble to the PHY to signal the
2978*8044SWilliam.Kucharski@Sun.COM * beginning of the MII instruction. This is done by sending 32
2979*8044SWilliam.Kucharski@Sun.COM * consecutive "1" bits.
2980*8044SWilliam.Kucharski@Sun.COM */
2981*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
2982*8044SWilliam.Kucharski@Sun.COM
2983*8044SWilliam.Kucharski@Sun.COM /* Now combine the remaining required fields that will indicate a
2984*8044SWilliam.Kucharski@Sun.COM * write operation. We use this method instead of calling the
2985*8044SWilliam.Kucharski@Sun.COM * e1000_shift_out_mdi_bits routine for each field in the command. The
2986*8044SWilliam.Kucharski@Sun.COM * format of a MII write instruction is as follows:
2987*8044SWilliam.Kucharski@Sun.COM * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
2988*8044SWilliam.Kucharski@Sun.COM */
2989*8044SWilliam.Kucharski@Sun.COM mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
2990*8044SWilliam.Kucharski@Sun.COM (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
2991*8044SWilliam.Kucharski@Sun.COM mdic <<= 16;
2992*8044SWilliam.Kucharski@Sun.COM mdic |= (uint32_t) phy_data;
2993*8044SWilliam.Kucharski@Sun.COM
2994*8044SWilliam.Kucharski@Sun.COM e1000_shift_out_mdi_bits(hw, mdic, 32);
2995*8044SWilliam.Kucharski@Sun.COM }
2996*8044SWilliam.Kucharski@Sun.COM
2997*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
2998*8044SWilliam.Kucharski@Sun.COM }
2999*8044SWilliam.Kucharski@Sun.COM
3000*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
3001*8044SWilliam.Kucharski@Sun.COM * Returns the PHY to the power-on reset state
3002*8044SWilliam.Kucharski@Sun.COM *
3003*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
3004*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
3005*8044SWilliam.Kucharski@Sun.COM static void
3006*8044SWilliam.Kucharski@Sun.COM e1000_phy_hw_reset(struct e1000_hw *hw)
3007*8044SWilliam.Kucharski@Sun.COM {
3008*8044SWilliam.Kucharski@Sun.COM uint32_t ctrl, ctrl_ext;
3009*8044SWilliam.Kucharski@Sun.COM
3010*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_phy_hw_reset");
3011*8044SWilliam.Kucharski@Sun.COM
3012*8044SWilliam.Kucharski@Sun.COM DEBUGOUT("Resetting Phy...\n");
3013*8044SWilliam.Kucharski@Sun.COM
3014*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type > e1000_82543) {
3015*8044SWilliam.Kucharski@Sun.COM /* Read the device control register and assert the E1000_CTRL_PHY_RST
3016*8044SWilliam.Kucharski@Sun.COM * bit. Then, take it out of reset.
3017*8044SWilliam.Kucharski@Sun.COM */
3018*8044SWilliam.Kucharski@Sun.COM ctrl = E1000_READ_REG(hw, CTRL);
3019*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
3020*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
3021*8044SWilliam.Kucharski@Sun.COM mdelay(10);
3022*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL, ctrl);
3023*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
3024*8044SWilliam.Kucharski@Sun.COM } else {
3025*8044SWilliam.Kucharski@Sun.COM /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
3026*8044SWilliam.Kucharski@Sun.COM * bit to put the PHY into reset. Then, take it out of reset.
3027*8044SWilliam.Kucharski@Sun.COM */
3028*8044SWilliam.Kucharski@Sun.COM ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
3029*8044SWilliam.Kucharski@Sun.COM ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
3030*8044SWilliam.Kucharski@Sun.COM ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
3031*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
3032*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
3033*8044SWilliam.Kucharski@Sun.COM mdelay(10);
3034*8044SWilliam.Kucharski@Sun.COM ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
3035*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
3036*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_FLUSH(hw);
3037*8044SWilliam.Kucharski@Sun.COM }
3038*8044SWilliam.Kucharski@Sun.COM udelay(150);
3039*8044SWilliam.Kucharski@Sun.COM }
3040*8044SWilliam.Kucharski@Sun.COM
3041*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
3042*8044SWilliam.Kucharski@Sun.COM * Resets the PHY
3043*8044SWilliam.Kucharski@Sun.COM *
3044*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
3045*8044SWilliam.Kucharski@Sun.COM *
3046*8044SWilliam.Kucharski@Sun.COM * Sets bit 15 of the MII Control regiser
3047*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
3048*8044SWilliam.Kucharski@Sun.COM static int
3049*8044SWilliam.Kucharski@Sun.COM e1000_phy_reset(struct e1000_hw *hw)
3050*8044SWilliam.Kucharski@Sun.COM {
3051*8044SWilliam.Kucharski@Sun.COM int32_t ret_val;
3052*8044SWilliam.Kucharski@Sun.COM uint16_t phy_data;
3053*8044SWilliam.Kucharski@Sun.COM
3054*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_phy_reset");
3055*8044SWilliam.Kucharski@Sun.COM
3056*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type != e1000_82541_rev_2) {
3057*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data)))
3058*8044SWilliam.Kucharski@Sun.COM return ret_val;
3059*8044SWilliam.Kucharski@Sun.COM
3060*8044SWilliam.Kucharski@Sun.COM phy_data |= MII_CR_RESET;
3061*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data)))
3062*8044SWilliam.Kucharski@Sun.COM return ret_val;
3063*8044SWilliam.Kucharski@Sun.COM
3064*8044SWilliam.Kucharski@Sun.COM udelay(1);
3065*8044SWilliam.Kucharski@Sun.COM } else e1000_phy_hw_reset(hw);
3066*8044SWilliam.Kucharski@Sun.COM
3067*8044SWilliam.Kucharski@Sun.COM if(hw->phy_type == e1000_phy_igp)
3068*8044SWilliam.Kucharski@Sun.COM e1000_phy_init_script(hw);
3069*8044SWilliam.Kucharski@Sun.COM
3070*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
3071*8044SWilliam.Kucharski@Sun.COM }
3072*8044SWilliam.Kucharski@Sun.COM
3073*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
3074*8044SWilliam.Kucharski@Sun.COM * Probes the expected PHY address for known PHY IDs
3075*8044SWilliam.Kucharski@Sun.COM *
3076*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
3077*8044SWilliam.Kucharski@Sun.COM ******************************************************************************/
3078*8044SWilliam.Kucharski@Sun.COM static int
3079*8044SWilliam.Kucharski@Sun.COM e1000_detect_gig_phy(struct e1000_hw *hw)
3080*8044SWilliam.Kucharski@Sun.COM {
3081*8044SWilliam.Kucharski@Sun.COM int32_t phy_init_status, ret_val;
3082*8044SWilliam.Kucharski@Sun.COM uint16_t phy_id_high, phy_id_low;
3083*8044SWilliam.Kucharski@Sun.COM boolean_t match = FALSE;
3084*8044SWilliam.Kucharski@Sun.COM
3085*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_detect_gig_phy");
3086*8044SWilliam.Kucharski@Sun.COM
3087*8044SWilliam.Kucharski@Sun.COM /* Read the PHY ID Registers to identify which PHY is onboard. */
3088*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high)))
3089*8044SWilliam.Kucharski@Sun.COM return ret_val;
3090*8044SWilliam.Kucharski@Sun.COM
3091*8044SWilliam.Kucharski@Sun.COM hw->phy_id = (uint32_t) (phy_id_high << 16);
3092*8044SWilliam.Kucharski@Sun.COM udelay(20);
3093*8044SWilliam.Kucharski@Sun.COM if((ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low)))
3094*8044SWilliam.Kucharski@Sun.COM return ret_val;
3095*8044SWilliam.Kucharski@Sun.COM
3096*8044SWilliam.Kucharski@Sun.COM hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
3097*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER
3098*8044SWilliam.Kucharski@Sun.COM hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK;
3099*8044SWilliam.Kucharski@Sun.COM #endif
3100*8044SWilliam.Kucharski@Sun.COM
3101*8044SWilliam.Kucharski@Sun.COM switch(hw->mac_type) {
3102*8044SWilliam.Kucharski@Sun.COM case e1000_82543:
3103*8044SWilliam.Kucharski@Sun.COM if(hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
3104*8044SWilliam.Kucharski@Sun.COM break;
3105*8044SWilliam.Kucharski@Sun.COM case e1000_82544:
3106*8044SWilliam.Kucharski@Sun.COM if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
3107*8044SWilliam.Kucharski@Sun.COM break;
3108*8044SWilliam.Kucharski@Sun.COM case e1000_82540:
3109*8044SWilliam.Kucharski@Sun.COM case e1000_82545:
3110*8044SWilliam.Kucharski@Sun.COM case e1000_82545_rev_3:
3111*8044SWilliam.Kucharski@Sun.COM case e1000_82546:
3112*8044SWilliam.Kucharski@Sun.COM case e1000_82546_rev_3:
3113*8044SWilliam.Kucharski@Sun.COM if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
3114*8044SWilliam.Kucharski@Sun.COM break;
3115*8044SWilliam.Kucharski@Sun.COM case e1000_82541:
3116*8044SWilliam.Kucharski@Sun.COM case e1000_82541_rev_2:
3117*8044SWilliam.Kucharski@Sun.COM case e1000_82547:
3118*8044SWilliam.Kucharski@Sun.COM case e1000_82547_rev_2:
3119*8044SWilliam.Kucharski@Sun.COM if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
3120*8044SWilliam.Kucharski@Sun.COM break;
3121*8044SWilliam.Kucharski@Sun.COM default:
3122*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
3123*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_CONFIG;
3124*8044SWilliam.Kucharski@Sun.COM }
3125*8044SWilliam.Kucharski@Sun.COM phy_init_status = e1000_set_phy_type(hw);
3126*8044SWilliam.Kucharski@Sun.COM
3127*8044SWilliam.Kucharski@Sun.COM if ((match) && (phy_init_status == E1000_SUCCESS)) {
3128*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id);
3129*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
3130*8044SWilliam.Kucharski@Sun.COM }
3131*8044SWilliam.Kucharski@Sun.COM DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id);
3132*8044SWilliam.Kucharski@Sun.COM return -E1000_ERR_PHY;
3133*8044SWilliam.Kucharski@Sun.COM }
3134*8044SWilliam.Kucharski@Sun.COM
3135*8044SWilliam.Kucharski@Sun.COM /******************************************************************************
3136*8044SWilliam.Kucharski@Sun.COM * Sets up eeprom variables in the hw struct. Must be called after mac_type
3137*8044SWilliam.Kucharski@Sun.COM * is configured.
3138*8044SWilliam.Kucharski@Sun.COM *
3139*8044SWilliam.Kucharski@Sun.COM * hw - Struct containing variables accessed by shared code
3140*8044SWilliam.Kucharski@Sun.COM *****************************************************************************/
3141*8044SWilliam.Kucharski@Sun.COM static void
3142*8044SWilliam.Kucharski@Sun.COM e1000_init_eeprom_params(struct e1000_hw *hw)
3143*8044SWilliam.Kucharski@Sun.COM {
3144*8044SWilliam.Kucharski@Sun.COM struct e1000_eeprom_info *eeprom = &hw->eeprom;
3145*8044SWilliam.Kucharski@Sun.COM uint32_t eecd = E1000_READ_REG(hw, EECD);
3146*8044SWilliam.Kucharski@Sun.COM uint16_t eeprom_size;
3147*8044SWilliam.Kucharski@Sun.COM
3148*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("e1000_init_eeprom_params");
3149*8044SWilliam.Kucharski@Sun.COM
3150*8044SWilliam.Kucharski@Sun.COM switch (hw->mac_type) {
3151*8044SWilliam.Kucharski@Sun.COM case e1000_82542_rev2_0:
3152*8044SWilliam.Kucharski@Sun.COM case e1000_82542_rev2_1:
3153*8044SWilliam.Kucharski@Sun.COM case e1000_82543:
3154*8044SWilliam.Kucharski@Sun.COM case e1000_82544:
3155*8044SWilliam.Kucharski@Sun.COM eeprom->type = e1000_eeprom_microwire;
3156*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 64;
3157*8044SWilliam.Kucharski@Sun.COM eeprom->opcode_bits = 3;
3158*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 6;
3159*8044SWilliam.Kucharski@Sun.COM eeprom->delay_usec = 50;
3160*8044SWilliam.Kucharski@Sun.COM break;
3161*8044SWilliam.Kucharski@Sun.COM case e1000_82540:
3162*8044SWilliam.Kucharski@Sun.COM case e1000_82545:
3163*8044SWilliam.Kucharski@Sun.COM case e1000_82545_rev_3:
3164*8044SWilliam.Kucharski@Sun.COM case e1000_82546:
3165*8044SWilliam.Kucharski@Sun.COM case e1000_82546_rev_3:
3166*8044SWilliam.Kucharski@Sun.COM eeprom->type = e1000_eeprom_microwire;
3167*8044SWilliam.Kucharski@Sun.COM eeprom->opcode_bits = 3;
3168*8044SWilliam.Kucharski@Sun.COM eeprom->delay_usec = 50;
3169*8044SWilliam.Kucharski@Sun.COM if(eecd & E1000_EECD_SIZE) {
3170*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 256;
3171*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 8;
3172*8044SWilliam.Kucharski@Sun.COM } else {
3173*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 64;
3174*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 6;
3175*8044SWilliam.Kucharski@Sun.COM }
3176*8044SWilliam.Kucharski@Sun.COM break;
3177*8044SWilliam.Kucharski@Sun.COM case e1000_82541:
3178*8044SWilliam.Kucharski@Sun.COM case e1000_82541_rev_2:
3179*8044SWilliam.Kucharski@Sun.COM case e1000_82547:
3180*8044SWilliam.Kucharski@Sun.COM case e1000_82547_rev_2:
3181*8044SWilliam.Kucharski@Sun.COM if (eecd & E1000_EECD_TYPE) {
3182*8044SWilliam.Kucharski@Sun.COM eeprom->type = e1000_eeprom_spi;
3183*8044SWilliam.Kucharski@Sun.COM if (eecd & E1000_EECD_ADDR_BITS) {
3184*8044SWilliam.Kucharski@Sun.COM eeprom->page_size = 32;
3185*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 16;
3186*8044SWilliam.Kucharski@Sun.COM } else {
3187*8044SWilliam.Kucharski@Sun.COM eeprom->page_size = 8;
3188*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 8;
3189*8044SWilliam.Kucharski@Sun.COM }
3190*8044SWilliam.Kucharski@Sun.COM } else {
3191*8044SWilliam.Kucharski@Sun.COM eeprom->type = e1000_eeprom_microwire;
3192*8044SWilliam.Kucharski@Sun.COM eeprom->opcode_bits = 3;
3193*8044SWilliam.Kucharski@Sun.COM eeprom->delay_usec = 50;
3194*8044SWilliam.Kucharski@Sun.COM if (eecd & E1000_EECD_ADDR_BITS) {
3195*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 256;
3196*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 8;
3197*8044SWilliam.Kucharski@Sun.COM } else {
3198*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 64;
3199*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 6;
3200*8044SWilliam.Kucharski@Sun.COM }
3201*8044SWilliam.Kucharski@Sun.COM }
3202*8044SWilliam.Kucharski@Sun.COM break;
3203*8044SWilliam.Kucharski@Sun.COM default:
3204*8044SWilliam.Kucharski@Sun.COM eeprom->type = e1000_eeprom_spi;
3205*8044SWilliam.Kucharski@Sun.COM if (eecd & E1000_EECD_ADDR_BITS) {
3206*8044SWilliam.Kucharski@Sun.COM eeprom->page_size = 32;
3207*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 16;
3208*8044SWilliam.Kucharski@Sun.COM } else {
3209*8044SWilliam.Kucharski@Sun.COM eeprom->page_size = 8;
3210*8044SWilliam.Kucharski@Sun.COM eeprom->address_bits = 8;
3211*8044SWilliam.Kucharski@Sun.COM }
3212*8044SWilliam.Kucharski@Sun.COM break;
3213*8044SWilliam.Kucharski@Sun.COM }
3214*8044SWilliam.Kucharski@Sun.COM
3215*8044SWilliam.Kucharski@Sun.COM if (eeprom->type == e1000_eeprom_spi) {
3216*8044SWilliam.Kucharski@Sun.COM eeprom->opcode_bits = 8;
3217*8044SWilliam.Kucharski@Sun.COM eeprom->delay_usec = 1;
3218*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 64;
3219*8044SWilliam.Kucharski@Sun.COM if (e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size) == 0) {
3220*8044SWilliam.Kucharski@Sun.COM eeprom_size &= EEPROM_SIZE_MASK;
3221*8044SWilliam.Kucharski@Sun.COM
3222*8044SWilliam.Kucharski@Sun.COM switch (eeprom_size) {
3223*8044SWilliam.Kucharski@Sun.COM case EEPROM_SIZE_16KB:
3224*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 8192;
3225*8044SWilliam.Kucharski@Sun.COM break;
3226*8044SWilliam.Kucharski@Sun.COM case EEPROM_SIZE_8KB:
3227*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 4096;
3228*8044SWilliam.Kucharski@Sun.COM break;
3229*8044SWilliam.Kucharski@Sun.COM case EEPROM_SIZE_4KB:
3230*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 2048;
3231*8044SWilliam.Kucharski@Sun.COM break;
3232*8044SWilliam.Kucharski@Sun.COM case EEPROM_SIZE_2KB:
3233*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 1024;
3234*8044SWilliam.Kucharski@Sun.COM break;
3235*8044SWilliam.Kucharski@Sun.COM case EEPROM_SIZE_1KB:
3236*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 512;
3237*8044SWilliam.Kucharski@Sun.COM break;
3238*8044SWilliam.Kucharski@Sun.COM case EEPROM_SIZE_512B:
3239*8044SWilliam.Kucharski@Sun.COM eeprom->word_size = 256;
3240*8044SWilliam.Kucharski@Sun.COM break;
3241*8044SWilliam.Kucharski@Sun.COM case EEPROM_SIZE_128B:
3242*8044SWilliam.Kucharski@Sun.COM default:
3243*8044SWilliam.Kucharski@Sun.COM break;
3244*8044SWilliam.Kucharski@Sun.COM }
3245*8044SWilliam.Kucharski@Sun.COM }
3246*8044SWilliam.Kucharski@Sun.COM }
3247*8044SWilliam.Kucharski@Sun.COM }
3248*8044SWilliam.Kucharski@Sun.COM
3249*8044SWilliam.Kucharski@Sun.COM /**
3250*8044SWilliam.Kucharski@Sun.COM * e1000_reset - Reset the adapter
3251*8044SWilliam.Kucharski@Sun.COM */
3252*8044SWilliam.Kucharski@Sun.COM
3253*8044SWilliam.Kucharski@Sun.COM static int
3254*8044SWilliam.Kucharski@Sun.COM e1000_reset(struct e1000_hw *hw)
3255*8044SWilliam.Kucharski@Sun.COM {
3256*8044SWilliam.Kucharski@Sun.COM uint32_t pba;
3257*8044SWilliam.Kucharski@Sun.COM /* Repartition Pba for greater than 9k mtu
3258*8044SWilliam.Kucharski@Sun.COM * To take effect CTRL.RST is required.
3259*8044SWilliam.Kucharski@Sun.COM */
3260*8044SWilliam.Kucharski@Sun.COM
3261*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type < e1000_82547) {
3262*8044SWilliam.Kucharski@Sun.COM pba = E1000_PBA_48K;
3263*8044SWilliam.Kucharski@Sun.COM } else {
3264*8044SWilliam.Kucharski@Sun.COM pba = E1000_PBA_30K;
3265*8044SWilliam.Kucharski@Sun.COM }
3266*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, PBA, pba);
3267*8044SWilliam.Kucharski@Sun.COM
3268*8044SWilliam.Kucharski@Sun.COM /* flow control settings */
3269*8044SWilliam.Kucharski@Sun.COM #if 0
3270*8044SWilliam.Kucharski@Sun.COM hw->fc_high_water = FC_DEFAULT_HI_THRESH;
3271*8044SWilliam.Kucharski@Sun.COM hw->fc_low_water = FC_DEFAULT_LO_THRESH;
3272*8044SWilliam.Kucharski@Sun.COM hw->fc_pause_time = FC_DEFAULT_TX_TIMER;
3273*8044SWilliam.Kucharski@Sun.COM hw->fc_send_xon = 1;
3274*8044SWilliam.Kucharski@Sun.COM hw->fc = hw->original_fc;
3275*8044SWilliam.Kucharski@Sun.COM #endif
3276*8044SWilliam.Kucharski@Sun.COM
3277*8044SWilliam.Kucharski@Sun.COM e1000_reset_hw(hw);
3278*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type >= e1000_82544)
3279*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG(hw, WUC, 0);
3280*8044SWilliam.Kucharski@Sun.COM return e1000_init_hw(hw);
3281*8044SWilliam.Kucharski@Sun.COM }
3282*8044SWilliam.Kucharski@Sun.COM
3283*8044SWilliam.Kucharski@Sun.COM /**
3284*8044SWilliam.Kucharski@Sun.COM * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
3285*8044SWilliam.Kucharski@Sun.COM * @adapter: board private structure to initialize
3286*8044SWilliam.Kucharski@Sun.COM *
3287*8044SWilliam.Kucharski@Sun.COM * e1000_sw_init initializes the Adapter private data structure.
3288*8044SWilliam.Kucharski@Sun.COM * Fields are initialized based on PCI device information and
3289*8044SWilliam.Kucharski@Sun.COM * OS network device settings (MTU size).
3290*8044SWilliam.Kucharski@Sun.COM **/
3291*8044SWilliam.Kucharski@Sun.COM
3292*8044SWilliam.Kucharski@Sun.COM static int
3293*8044SWilliam.Kucharski@Sun.COM e1000_sw_init(struct pci_device *pdev, struct e1000_hw *hw)
3294*8044SWilliam.Kucharski@Sun.COM {
3295*8044SWilliam.Kucharski@Sun.COM int result;
3296*8044SWilliam.Kucharski@Sun.COM
3297*8044SWilliam.Kucharski@Sun.COM /* PCI config space info */
3298*8044SWilliam.Kucharski@Sun.COM pci_read_config_word(pdev, PCI_VENDOR_ID, &hw->vendor_id);
3299*8044SWilliam.Kucharski@Sun.COM pci_read_config_word(pdev, PCI_DEVICE_ID, &hw->device_id);
3300*8044SWilliam.Kucharski@Sun.COM pci_read_config_byte(pdev, PCI_REVISION, &hw->revision_id);
3301*8044SWilliam.Kucharski@Sun.COM #if 0
3302*8044SWilliam.Kucharski@Sun.COM pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID,
3303*8044SWilliam.Kucharski@Sun.COM &hw->subsystem_vendor_id);
3304*8044SWilliam.Kucharski@Sun.COM pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id);
3305*8044SWilliam.Kucharski@Sun.COM #endif
3306*8044SWilliam.Kucharski@Sun.COM
3307*8044SWilliam.Kucharski@Sun.COM pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
3308*8044SWilliam.Kucharski@Sun.COM
3309*8044SWilliam.Kucharski@Sun.COM /* identify the MAC */
3310*8044SWilliam.Kucharski@Sun.COM
3311*8044SWilliam.Kucharski@Sun.COM result = e1000_set_mac_type(hw);
3312*8044SWilliam.Kucharski@Sun.COM if (result) {
3313*8044SWilliam.Kucharski@Sun.COM E1000_ERR("Unknown MAC Type\n");
3314*8044SWilliam.Kucharski@Sun.COM return result;
3315*8044SWilliam.Kucharski@Sun.COM }
3316*8044SWilliam.Kucharski@Sun.COM
3317*8044SWilliam.Kucharski@Sun.COM /* initialize eeprom parameters */
3318*8044SWilliam.Kucharski@Sun.COM
3319*8044SWilliam.Kucharski@Sun.COM e1000_init_eeprom_params(hw);
3320*8044SWilliam.Kucharski@Sun.COM
3321*8044SWilliam.Kucharski@Sun.COM #if 0
3322*8044SWilliam.Kucharski@Sun.COM if((hw->mac_type == e1000_82541) ||
3323*8044SWilliam.Kucharski@Sun.COM (hw->mac_type == e1000_82547) ||
3324*8044SWilliam.Kucharski@Sun.COM (hw->mac_type == e1000_82541_rev_2) ||
3325*8044SWilliam.Kucharski@Sun.COM (hw->mac_type == e1000_82547_rev_2))
3326*8044SWilliam.Kucharski@Sun.COM hw->phy_init_script = 1;
3327*8044SWilliam.Kucharski@Sun.COM #endif
3328*8044SWilliam.Kucharski@Sun.COM
3329*8044SWilliam.Kucharski@Sun.COM e1000_set_media_type(hw);
3330*8044SWilliam.Kucharski@Sun.COM
3331*8044SWilliam.Kucharski@Sun.COM #if 0
3332*8044SWilliam.Kucharski@Sun.COM if(hw->mac_type < e1000_82543)
3333*8044SWilliam.Kucharski@Sun.COM hw->report_tx_early = 0;
3334*8044SWilliam.Kucharski@Sun.COM else
3335*8044SWilliam.Kucharski@Sun.COM hw->report_tx_early = 1;
3336*8044SWilliam.Kucharski@Sun.COM
3337*8044SWilliam.Kucharski@Sun.COM hw->wait_autoneg_complete = FALSE;
3338*8044SWilliam.Kucharski@Sun.COM #endif
3339*8044SWilliam.Kucharski@Sun.COM hw->tbi_compatibility_en = TRUE;
3340*8044SWilliam.Kucharski@Sun.COM #if 0
3341*8044SWilliam.Kucharski@Sun.COM hw->adaptive_ifs = TRUE;
3342*8044SWilliam.Kucharski@Sun.COM
3343*8044SWilliam.Kucharski@Sun.COM /* Copper options */
3344*8044SWilliam.Kucharski@Sun.COM
3345*8044SWilliam.Kucharski@Sun.COM if(hw->media_type == e1000_media_type_copper) {
3346*8044SWilliam.Kucharski@Sun.COM hw->mdix = AUTO_ALL_MODES;
3347*8044SWilliam.Kucharski@Sun.COM hw->disable_polarity_correction = FALSE;
3348*8044SWilliam.Kucharski@Sun.COM hw->master_slave = E1000_MASTER_SLAVE;
3349*8044SWilliam.Kucharski@Sun.COM }
3350*8044SWilliam.Kucharski@Sun.COM #endif
3351*8044SWilliam.Kucharski@Sun.COM return E1000_SUCCESS;
3352*8044SWilliam.Kucharski@Sun.COM }
3353*8044SWilliam.Kucharski@Sun.COM
3354*8044SWilliam.Kucharski@Sun.COM static void fill_rx (void)
3355*8044SWilliam.Kucharski@Sun.COM {
3356*8044SWilliam.Kucharski@Sun.COM struct e1000_rx_desc *rd;
3357*8044SWilliam.Kucharski@Sun.COM rx_last = rx_tail;
3358*8044SWilliam.Kucharski@Sun.COM rd = rx_base + rx_tail;
3359*8044SWilliam.Kucharski@Sun.COM rx_tail = (rx_tail + 1) % 8;
3360*8044SWilliam.Kucharski@Sun.COM memset (rd, 0, 16);
3361*8044SWilliam.Kucharski@Sun.COM rd->buffer_addr = virt_to_bus(&packet);
3362*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RDT, rx_tail);
3363*8044SWilliam.Kucharski@Sun.COM }
3364*8044SWilliam.Kucharski@Sun.COM
3365*8044SWilliam.Kucharski@Sun.COM static void init_descriptor (void)
3366*8044SWilliam.Kucharski@Sun.COM {
3367*8044SWilliam.Kucharski@Sun.COM unsigned long ptr;
3368*8044SWilliam.Kucharski@Sun.COM unsigned long tctl;
3369*8044SWilliam.Kucharski@Sun.COM
3370*8044SWilliam.Kucharski@Sun.COM ptr = virt_to_phys(tx_pool);
3371*8044SWilliam.Kucharski@Sun.COM if (ptr & 0xf)
3372*8044SWilliam.Kucharski@Sun.COM ptr = (ptr + 0x10) & (~0xf);
3373*8044SWilliam.Kucharski@Sun.COM
3374*8044SWilliam.Kucharski@Sun.COM tx_base = phys_to_virt(ptr);
3375*8044SWilliam.Kucharski@Sun.COM
3376*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TDBAL, virt_to_bus(tx_base));
3377*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TDBAH, 0);
3378*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TDLEN, 128);
3379*8044SWilliam.Kucharski@Sun.COM
3380*8044SWilliam.Kucharski@Sun.COM /* Setup the HW Tx Head and Tail descriptor pointers */
3381*8044SWilliam.Kucharski@Sun.COM
3382*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TDH, 0);
3383*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TDT, 0);
3384*8044SWilliam.Kucharski@Sun.COM tx_tail = 0;
3385*8044SWilliam.Kucharski@Sun.COM
3386*8044SWilliam.Kucharski@Sun.COM /* Program the Transmit Control Register */
3387*8044SWilliam.Kucharski@Sun.COM
3388*8044SWilliam.Kucharski@Sun.COM #ifdef LINUX_DRIVER_TCTL
3389*8044SWilliam.Kucharski@Sun.COM tctl = E1000_READ_REG(&hw, TCTL);
3390*8044SWilliam.Kucharski@Sun.COM
3391*8044SWilliam.Kucharski@Sun.COM tctl &= ~E1000_TCTL_CT;
3392*8044SWilliam.Kucharski@Sun.COM tctl |= E1000_TCTL_EN | E1000_TCTL_PSP |
3393*8044SWilliam.Kucharski@Sun.COM (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
3394*8044SWilliam.Kucharski@Sun.COM #else
3395*8044SWilliam.Kucharski@Sun.COM tctl = E1000_TCTL_PSP | E1000_TCTL_EN |
3396*8044SWilliam.Kucharski@Sun.COM (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT) |
3397*8044SWilliam.Kucharski@Sun.COM (E1000_HDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
3398*8044SWilliam.Kucharski@Sun.COM #endif
3399*8044SWilliam.Kucharski@Sun.COM
3400*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TCTL, tctl);
3401*8044SWilliam.Kucharski@Sun.COM
3402*8044SWilliam.Kucharski@Sun.COM e1000_config_collision_dist(&hw);
3403*8044SWilliam.Kucharski@Sun.COM
3404*8044SWilliam.Kucharski@Sun.COM
3405*8044SWilliam.Kucharski@Sun.COM rx_tail = 0;
3406*8044SWilliam.Kucharski@Sun.COM /* disable receive */
3407*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RCTL, 0);
3408*8044SWilliam.Kucharski@Sun.COM ptr = virt_to_phys(rx_pool);
3409*8044SWilliam.Kucharski@Sun.COM if (ptr & 0xf)
3410*8044SWilliam.Kucharski@Sun.COM ptr = (ptr + 0x10) & (~0xf);
3411*8044SWilliam.Kucharski@Sun.COM rx_base = phys_to_virt(ptr);
3412*8044SWilliam.Kucharski@Sun.COM
3413*8044SWilliam.Kucharski@Sun.COM /* Setup the Base and Length of the Rx Descriptor Ring */
3414*8044SWilliam.Kucharski@Sun.COM
3415*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RDBAL, virt_to_bus(rx_base));
3416*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RDBAH, 0);
3417*8044SWilliam.Kucharski@Sun.COM
3418*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RDLEN, 128);
3419*8044SWilliam.Kucharski@Sun.COM
3420*8044SWilliam.Kucharski@Sun.COM /* Setup the HW Rx Head and Tail Descriptor Pointers */
3421*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RDH, 0);
3422*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RDT, 0);
3423*8044SWilliam.Kucharski@Sun.COM
3424*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RCTL,
3425*8044SWilliam.Kucharski@Sun.COM E1000_RCTL_EN |
3426*8044SWilliam.Kucharski@Sun.COM E1000_RCTL_BAM |
3427*8044SWilliam.Kucharski@Sun.COM E1000_RCTL_SZ_2048 |
3428*8044SWilliam.Kucharski@Sun.COM E1000_RCTL_MPE);
3429*8044SWilliam.Kucharski@Sun.COM fill_rx();
3430*8044SWilliam.Kucharski@Sun.COM }
3431*8044SWilliam.Kucharski@Sun.COM
3432*8044SWilliam.Kucharski@Sun.COM
3433*8044SWilliam.Kucharski@Sun.COM
3434*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3435*8044SWilliam.Kucharski@Sun.COM POLL - Wait for a frame
3436*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3437*8044SWilliam.Kucharski@Sun.COM static int
3438*8044SWilliam.Kucharski@Sun.COM e1000_poll (struct nic *nic, int retrieve)
3439*8044SWilliam.Kucharski@Sun.COM {
3440*8044SWilliam.Kucharski@Sun.COM /* return true if there's an ethernet packet ready to read */
3441*8044SWilliam.Kucharski@Sun.COM /* nic->packet should contain data on return */
3442*8044SWilliam.Kucharski@Sun.COM /* nic->packetlen should contain length of data */
3443*8044SWilliam.Kucharski@Sun.COM struct e1000_rx_desc *rd;
3444*8044SWilliam.Kucharski@Sun.COM
3445*8044SWilliam.Kucharski@Sun.COM rd = rx_base + rx_last;
3446*8044SWilliam.Kucharski@Sun.COM if (!rd->status & E1000_RXD_STAT_DD)
3447*8044SWilliam.Kucharski@Sun.COM return 0;
3448*8044SWilliam.Kucharski@Sun.COM
3449*8044SWilliam.Kucharski@Sun.COM if ( ! retrieve ) return 1;
3450*8044SWilliam.Kucharski@Sun.COM
3451*8044SWilliam.Kucharski@Sun.COM // printf("recv: packet %! -> %! len=%d \n", packet+6, packet,rd->Length);
3452*8044SWilliam.Kucharski@Sun.COM memcpy (nic->packet, packet, rd->length);
3453*8044SWilliam.Kucharski@Sun.COM nic->packetlen = rd->length;
3454*8044SWilliam.Kucharski@Sun.COM fill_rx ();
3455*8044SWilliam.Kucharski@Sun.COM return 1;
3456*8044SWilliam.Kucharski@Sun.COM }
3457*8044SWilliam.Kucharski@Sun.COM
3458*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3459*8044SWilliam.Kucharski@Sun.COM TRANSMIT - Transmit a frame
3460*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3461*8044SWilliam.Kucharski@Sun.COM static void
3462*8044SWilliam.Kucharski@Sun.COM e1000_transmit (struct nic *nic, const char *d, /* Destination */
3463*8044SWilliam.Kucharski@Sun.COM unsigned int type, /* Type */
3464*8044SWilliam.Kucharski@Sun.COM unsigned int size, /* size */
3465*8044SWilliam.Kucharski@Sun.COM const char *p) /* Packet */
3466*8044SWilliam.Kucharski@Sun.COM {
3467*8044SWilliam.Kucharski@Sun.COM /* send the packet to destination */
3468*8044SWilliam.Kucharski@Sun.COM struct eth_hdr {
3469*8044SWilliam.Kucharski@Sun.COM unsigned char dst_addr[ETH_ALEN];
3470*8044SWilliam.Kucharski@Sun.COM unsigned char src_addr[ETH_ALEN];
3471*8044SWilliam.Kucharski@Sun.COM unsigned short type;
3472*8044SWilliam.Kucharski@Sun.COM } hdr;
3473*8044SWilliam.Kucharski@Sun.COM struct e1000_tx_desc *txhd; /* header */
3474*8044SWilliam.Kucharski@Sun.COM struct e1000_tx_desc *txp; /* payload */
3475*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("send");
3476*8044SWilliam.Kucharski@Sun.COM
3477*8044SWilliam.Kucharski@Sun.COM memcpy (&hdr.dst_addr, d, ETH_ALEN);
3478*8044SWilliam.Kucharski@Sun.COM memcpy (&hdr.src_addr, nic->node_addr, ETH_ALEN);
3479*8044SWilliam.Kucharski@Sun.COM
3480*8044SWilliam.Kucharski@Sun.COM hdr.type = htons (type);
3481*8044SWilliam.Kucharski@Sun.COM txhd = tx_base + tx_tail;
3482*8044SWilliam.Kucharski@Sun.COM tx_tail = (tx_tail + 1) % 8;
3483*8044SWilliam.Kucharski@Sun.COM txp = tx_base + tx_tail;
3484*8044SWilliam.Kucharski@Sun.COM tx_tail = (tx_tail + 1) % 8;
3485*8044SWilliam.Kucharski@Sun.COM
3486*8044SWilliam.Kucharski@Sun.COM txhd->buffer_addr = virt_to_bus (&hdr);
3487*8044SWilliam.Kucharski@Sun.COM txhd->lower.data = sizeof (hdr);
3488*8044SWilliam.Kucharski@Sun.COM txhd->upper.data = 0;
3489*8044SWilliam.Kucharski@Sun.COM
3490*8044SWilliam.Kucharski@Sun.COM txp->buffer_addr = virt_to_bus(p);
3491*8044SWilliam.Kucharski@Sun.COM txp->lower.data = E1000_TXD_CMD_RPS | E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS | size;
3492*8044SWilliam.Kucharski@Sun.COM txp->upper.data = 0;
3493*8044SWilliam.Kucharski@Sun.COM
3494*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TDT, tx_tail);
3495*8044SWilliam.Kucharski@Sun.COM while (!(txp->upper.data & E1000_TXD_STAT_DD)) {
3496*8044SWilliam.Kucharski@Sun.COM udelay(10); /* give the nic a chance to write to the register */
3497*8044SWilliam.Kucharski@Sun.COM poll_interruptions();
3498*8044SWilliam.Kucharski@Sun.COM }
3499*8044SWilliam.Kucharski@Sun.COM DEBUGFUNC("send end");
3500*8044SWilliam.Kucharski@Sun.COM }
3501*8044SWilliam.Kucharski@Sun.COM
3502*8044SWilliam.Kucharski@Sun.COM
3503*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3504*8044SWilliam.Kucharski@Sun.COM DISABLE - Turn off ethernet interface
3505*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3506*8044SWilliam.Kucharski@Sun.COM static void e1000_disable (struct dev *dev __unused)
3507*8044SWilliam.Kucharski@Sun.COM {
3508*8044SWilliam.Kucharski@Sun.COM /* Clear the transmit ring */
3509*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TDH, 0);
3510*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TDT, 0);
3511*8044SWilliam.Kucharski@Sun.COM
3512*8044SWilliam.Kucharski@Sun.COM /* Clear the receive ring */
3513*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RDH, 0);
3514*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RDT, 0);
3515*8044SWilliam.Kucharski@Sun.COM
3516*8044SWilliam.Kucharski@Sun.COM /* put the card in its initial state */
3517*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, CTRL, E1000_CTRL_RST);
3518*8044SWilliam.Kucharski@Sun.COM
3519*8044SWilliam.Kucharski@Sun.COM /* Turn off the ethernet interface */
3520*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, RCTL, 0);
3521*8044SWilliam.Kucharski@Sun.COM E1000_WRITE_REG (&hw, TCTL, 0);
3522*8044SWilliam.Kucharski@Sun.COM mdelay (10);
3523*8044SWilliam.Kucharski@Sun.COM
3524*8044SWilliam.Kucharski@Sun.COM /* Unmap my window to the device */
3525*8044SWilliam.Kucharski@Sun.COM iounmap(hw.hw_addr);
3526*8044SWilliam.Kucharski@Sun.COM }
3527*8044SWilliam.Kucharski@Sun.COM
3528*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3529*8044SWilliam.Kucharski@Sun.COM IRQ - Enable, Disable, or Force interrupts
3530*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3531*8044SWilliam.Kucharski@Sun.COM static void e1000_irq(struct nic *nic __unused, irq_action_t action __unused)
3532*8044SWilliam.Kucharski@Sun.COM {
3533*8044SWilliam.Kucharski@Sun.COM switch ( action ) {
3534*8044SWilliam.Kucharski@Sun.COM case DISABLE :
3535*8044SWilliam.Kucharski@Sun.COM break;
3536*8044SWilliam.Kucharski@Sun.COM case ENABLE :
3537*8044SWilliam.Kucharski@Sun.COM break;
3538*8044SWilliam.Kucharski@Sun.COM case FORCE :
3539*8044SWilliam.Kucharski@Sun.COM break;
3540*8044SWilliam.Kucharski@Sun.COM }
3541*8044SWilliam.Kucharski@Sun.COM }
3542*8044SWilliam.Kucharski@Sun.COM
3543*8044SWilliam.Kucharski@Sun.COM #define IORESOURCE_IO 0x00000100 /* Resource type */
3544*8044SWilliam.Kucharski@Sun.COM #define BAR_0 0
3545*8044SWilliam.Kucharski@Sun.COM #define BAR_1 1
3546*8044SWilliam.Kucharski@Sun.COM #define BAR_5 5
3547*8044SWilliam.Kucharski@Sun.COM
3548*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
3549*8044SWilliam.Kucharski@Sun.COM PROBE - Look for an adapter, this routine's visible to the outside
3550*8044SWilliam.Kucharski@Sun.COM You should omit the last argument struct pci_device * for a non-PCI NIC
3551*8044SWilliam.Kucharski@Sun.COM ***************************************************************************/
3552*8044SWilliam.Kucharski@Sun.COM static int e1000_probe(struct dev *dev, struct pci_device *p)
3553*8044SWilliam.Kucharski@Sun.COM {
3554*8044SWilliam.Kucharski@Sun.COM struct nic *nic = (struct nic *)dev;
3555*8044SWilliam.Kucharski@Sun.COM unsigned long mmio_start, mmio_len;
3556*8044SWilliam.Kucharski@Sun.COM int ret_val, i;
3557*8044SWilliam.Kucharski@Sun.COM
3558*8044SWilliam.Kucharski@Sun.COM if (p == 0)
3559*8044SWilliam.Kucharski@Sun.COM return 0;
3560*8044SWilliam.Kucharski@Sun.COM /* Initialize hw with default values */
3561*8044SWilliam.Kucharski@Sun.COM memset(&hw, 0, sizeof(hw));
3562*8044SWilliam.Kucharski@Sun.COM hw.pdev = p;
3563*8044SWilliam.Kucharski@Sun.COM
3564*8044SWilliam.Kucharski@Sun.COM #if 1
3565*8044SWilliam.Kucharski@Sun.COM /* Are these variables needed? */
3566*8044SWilliam.Kucharski@Sun.COM hw.fc = e1000_fc_none;
3567*8044SWilliam.Kucharski@Sun.COM #if 0
3568*8044SWilliam.Kucharski@Sun.COM hw.original_fc = e1000_fc_none;
3569*8044SWilliam.Kucharski@Sun.COM #endif
3570*8044SWilliam.Kucharski@Sun.COM hw.autoneg_failed = 0;
3571*8044SWilliam.Kucharski@Sun.COM #if 0
3572*8044SWilliam.Kucharski@Sun.COM hw.get_link_status = TRUE;
3573*8044SWilliam.Kucharski@Sun.COM #endif
3574*8044SWilliam.Kucharski@Sun.COM #endif
3575*8044SWilliam.Kucharski@Sun.COM
3576*8044SWilliam.Kucharski@Sun.COM mmio_start = pci_bar_start(p, PCI_BASE_ADDRESS_0);
3577*8044SWilliam.Kucharski@Sun.COM mmio_len = pci_bar_size(p, PCI_BASE_ADDRESS_0);
3578*8044SWilliam.Kucharski@Sun.COM hw.hw_addr = ioremap(mmio_start, mmio_len);
3579*8044SWilliam.Kucharski@Sun.COM
3580*8044SWilliam.Kucharski@Sun.COM for(i = BAR_1; i <= BAR_5; i++) {
3581*8044SWilliam.Kucharski@Sun.COM if(pci_bar_size(p, i) == 0)
3582*8044SWilliam.Kucharski@Sun.COM continue;
3583*8044SWilliam.Kucharski@Sun.COM if(pci_find_capability(p, i) & IORESOURCE_IO) {
3584*8044SWilliam.Kucharski@Sun.COM hw.io_base = pci_bar_start(p, i);
3585*8044SWilliam.Kucharski@Sun.COM break;
3586*8044SWilliam.Kucharski@Sun.COM }
3587*8044SWilliam.Kucharski@Sun.COM }
3588*8044SWilliam.Kucharski@Sun.COM
3589*8044SWilliam.Kucharski@Sun.COM adjust_pci_device(p);
3590*8044SWilliam.Kucharski@Sun.COM
3591*8044SWilliam.Kucharski@Sun.COM nic->ioaddr = p->ioaddr & ~3;
3592*8044SWilliam.Kucharski@Sun.COM nic->irqno = 0;
3593*8044SWilliam.Kucharski@Sun.COM
3594*8044SWilliam.Kucharski@Sun.COM /* From Matt Hortman <mbhortman@acpthinclient.com> */
3595*8044SWilliam.Kucharski@Sun.COM /* MAC and Phy settings */
3596*8044SWilliam.Kucharski@Sun.COM
3597*8044SWilliam.Kucharski@Sun.COM /* setup the private structure */
3598*8044SWilliam.Kucharski@Sun.COM if (e1000_sw_init(p, &hw) < 0) {
3599*8044SWilliam.Kucharski@Sun.COM iounmap(hw.hw_addr);
3600*8044SWilliam.Kucharski@Sun.COM return 0;
3601*8044SWilliam.Kucharski@Sun.COM }
3602*8044SWilliam.Kucharski@Sun.COM
3603*8044SWilliam.Kucharski@Sun.COM /* make sure the EEPROM is good */
3604*8044SWilliam.Kucharski@Sun.COM
3605*8044SWilliam.Kucharski@Sun.COM if (e1000_validate_eeprom_checksum(&hw) < 0) {
3606*8044SWilliam.Kucharski@Sun.COM printf ("The EEPROM Checksum Is Not Valid\n");
3607*8044SWilliam.Kucharski@Sun.COM iounmap(hw.hw_addr);
3608*8044SWilliam.Kucharski@Sun.COM return 0;
3609*8044SWilliam.Kucharski@Sun.COM }
3610*8044SWilliam.Kucharski@Sun.COM
3611*8044SWilliam.Kucharski@Sun.COM /* copy the MAC address out of the EEPROM */
3612*8044SWilliam.Kucharski@Sun.COM
3613*8044SWilliam.Kucharski@Sun.COM e1000_read_mac_addr(&hw);
3614*8044SWilliam.Kucharski@Sun.COM memcpy (nic->node_addr, hw.mac_addr, ETH_ALEN);
3615*8044SWilliam.Kucharski@Sun.COM
3616*8044SWilliam.Kucharski@Sun.COM printf("Ethernet addr: %!\n", nic->node_addr);
3617*8044SWilliam.Kucharski@Sun.COM
3618*8044SWilliam.Kucharski@Sun.COM /* reset the hardware with the new settings */
3619*8044SWilliam.Kucharski@Sun.COM
3620*8044SWilliam.Kucharski@Sun.COM ret_val = e1000_reset(&hw);
3621*8044SWilliam.Kucharski@Sun.COM if (ret_val < 0) {
3622*8044SWilliam.Kucharski@Sun.COM if ((ret_val == -E1000_ERR_NOLINK) ||
3623*8044SWilliam.Kucharski@Sun.COM (ret_val == -E1000_ERR_TIMEOUT)) {
3624*8044SWilliam.Kucharski@Sun.COM E1000_ERR("Valid Link not detected\n");
3625*8044SWilliam.Kucharski@Sun.COM } else {
3626*8044SWilliam.Kucharski@Sun.COM E1000_ERR("Hardware Initialization Failed\n");
3627*8044SWilliam.Kucharski@Sun.COM }
3628*8044SWilliam.Kucharski@Sun.COM iounmap(hw.hw_addr);
3629*8044SWilliam.Kucharski@Sun.COM return 0;
3630*8044SWilliam.Kucharski@Sun.COM }
3631*8044SWilliam.Kucharski@Sun.COM init_descriptor();
3632*8044SWilliam.Kucharski@Sun.COM
3633*8044SWilliam.Kucharski@Sun.COM /* point to NIC specific routines */
3634*8044SWilliam.Kucharski@Sun.COM dev->disable = e1000_disable;
3635*8044SWilliam.Kucharski@Sun.COM nic->poll = e1000_poll;
3636*8044SWilliam.Kucharski@Sun.COM nic->transmit = e1000_transmit;
3637*8044SWilliam.Kucharski@Sun.COM nic->irq = e1000_irq;
3638*8044SWilliam.Kucharski@Sun.COM
3639*8044SWilliam.Kucharski@Sun.COM return 1;
3640*8044SWilliam.Kucharski@Sun.COM }
3641*8044SWilliam.Kucharski@Sun.COM
3642*8044SWilliam.Kucharski@Sun.COM static struct pci_id e1000_nics[] = {
3643*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1000, "e1000-82542", "Intel EtherExpressPro1000"),
3644*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1001, "e1000-82543gc-fiber", "Intel EtherExpressPro1000 82543GC Fiber"),
3645*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1004, "e1000-82543gc-copper", "Intel EtherExpressPro1000 82543GC Copper"),
3646*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1008, "e1000-82544ei-copper", "Intel EtherExpressPro1000 82544EI Copper"),
3647*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1009, "e1000-82544ei-fiber", "Intel EtherExpressPro1000 82544EI Fiber"),
3648*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x100C, "e1000-82544gc-copper", "Intel EtherExpressPro1000 82544GC Copper"),
3649*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x100D, "e1000-82544gc-lom", "Intel EtherExpressPro1000 82544GC LOM"),
3650*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x100E, "e1000-82540em", "Intel EtherExpressPro1000 82540EM"),
3651*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x100F, "e1000-82545em-copper", "Intel EtherExpressPro1000 82545EM Copper"),
3652*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1010, "e1000-82546eb-copper", "Intel EtherExpressPro1000 82546EB Copper"),
3653*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1011, "e1000-82545em-fiber", "Intel EtherExpressPro1000 82545EM Fiber"),
3654*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1012, "e1000-82546eb-fiber", "Intel EtherExpressPro1000 82546EB Copper"),
3655*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1013, "e1000-82541ei", "Intel EtherExpressPro1000 82541EI"),
3656*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1015, "e1000-82540em-lom", "Intel EtherExpressPro1000 82540EM LOM"),
3657*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1016, "e1000-82540ep-lom", "Intel EtherExpressPro1000 82540EP LOM"),
3658*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1017, "e1000-82540ep", "Intel EtherExpressPro1000 82540EP"),
3659*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1018, "e1000-82541ep", "Intel EtherExpressPro1000 82541EP"),
3660*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1019, "e1000-82547ei", "Intel EtherExpressPro1000 82547EI"),
3661*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x101d, "e1000-82546eb-quad-copper", "Intel EtherExpressPro1000 82546EB Quad Copper"),
3662*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x101e, "e1000-82540ep-lp", "Intel EtherExpressPro1000 82540EP LP"),
3663*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1026, "e1000-82545gm-copper", "Intel EtherExpressPro1000 82545GM Copper"),
3664*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1027, "e1000-82545gm-fiber", "Intel EtherExpressPro1000 82545GM Fiber"),
3665*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1028, "e1000-82545gm-serdes", "Intel EtherExpressPro1000 82545GM SERDES"),
3666*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1075, "e1000-82547gi", "Intel EtherExpressPro1000 82547GI"),
3667*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1076, "e1000-82541gi", "Intel EtherExpressPro1000 82541GI"),
3668*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1077, "e1000-82541gi-mobile", "Intel EtherExpressPro1000 82541GI Mobile"),
3669*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1078, "e1000-82541er", "Intel EtherExpressPro1000 82541ER"),
3670*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x1079, "e1000-82546gb-copper", "Intel EtherExpressPro1000 82546GB Copper"),
3671*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x107a, "e1000-82546gb-fiber", "Intel EtherExpressPro1000 82546GB Fiber"),
3672*8044SWilliam.Kucharski@Sun.COM PCI_ROM(0x8086, 0x107b, "e1000-82546gb-serdes", "Intel EtherExpressPro1000 82546GB SERDES"),
3673*8044SWilliam.Kucharski@Sun.COM };
3674*8044SWilliam.Kucharski@Sun.COM
3675*8044SWilliam.Kucharski@Sun.COM struct pci_driver e1000_driver = {
3676*8044SWilliam.Kucharski@Sun.COM .type = NIC_DRIVER,
3677*8044SWilliam.Kucharski@Sun.COM .name = "E1000",
3678*8044SWilliam.Kucharski@Sun.COM .probe = e1000_probe,
3679*8044SWilliam.Kucharski@Sun.COM .ids = e1000_nics,
3680*8044SWilliam.Kucharski@Sun.COM .id_count = sizeof(e1000_nics)/sizeof(e1000_nics[0]),
3681*8044SWilliam.Kucharski@Sun.COM .class = 0,
3682*8044SWilliam.Kucharski@Sun.COM };
3683