xref: /rk3399_rockchip-uboot/drivers/net/smc91111.c (revision 2439e4bfa111babf4bc07ba20efbf3e36036813e)
1*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------------------
2*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . smc91111.c
3*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . This is a driver for SMSC's 91C111 single-chip Ethernet device.
4*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
5*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . (C) Copyright 2002
6*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Rolf Offermanns <rof@sysgo.de>
8*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
9*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Copyright (C) 2001 Standard Microsystems Corporation (SMSC)
10*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	 Developed by Simple Network Magic Corporation (SNMC)
11*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Copyright (C) 1996 by Erik Stahlman (ES)
12*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
13*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . This program is free software; you can redistribute it and/or modify
14*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . it under the terms of the GNU General Public License as published by
15*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . the Free Software Foundation; either version 2 of the License, or
16*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . (at your option) any later version.
17*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
18*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . This program is distributed in the hope that it will be useful,
19*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . but WITHOUT ANY WARRANTY; without even the implied warranty of
20*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
21*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . GNU General Public License for more details.
22*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
23*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . You should have received a copy of the GNU General Public License
24*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . along with this program; if not, write to the Free Software
25*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
26*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
27*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Information contained in this file was obtained from the LAN91C111
28*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . manual from SMC.  To get a copy, if you really want one, you can find
29*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . information under www.smsc.com.
30*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
31*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
32*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . "Features" of the SMC chip:
33*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .   Integrated PHY/MAC for 10/100BaseT Operation
34*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .   Supports internal and external MII
35*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .   Integrated 8K packet memory
36*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .   EEPROM interface for configuration
37*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
38*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Arguments:
39*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	io	= for the base address
40*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	irq	= for the IRQ
41*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
42*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . author:
43*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Erik Stahlman				( erik@vt.edu )
44*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Daris A Nevil				( dnevil@snmc.com )
45*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
46*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
47*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Hardware multicast code from Peter Cammaert ( pc@denkart.be )
48*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
49*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Sources:
50*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .    o	  SMSC LAN91C111 databook (www.smsc.com)
51*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .    o	  smc9194.c by Erik Stahlman
52*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .    o	  skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov )
53*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
54*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . History:
55*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	06/19/03  Richard Woodruff Made u-boot environment aware and added mac addr checks.
56*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	10/17/01  Marco Hasewinkel Modify for DNP/1110
57*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	07/25/01  Woojung Huh	   Modify for ADS Bitsy
58*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	04/25/01  Daris A Nevil	   Initial public release through SMSC
59*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	03/16/01  Daris A Nevil	   Modified smc9194.c for use with LAN91C111
60*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  ----------------------------------------------------------------------------*/
61*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
62*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
63*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h>
64*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <config.h>
65*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "smc91111.h"
66*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h>
67*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
68*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DRIVER_SMC91111
69*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
70*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Use power-down feature of the chip */
71*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define POWER_DOWN	0
72*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
73*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define NO_AUTOPROBE
74*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
75*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SMC_DEBUG 0
76*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
77*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if SMC_DEBUG > 1
78*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static const char version[] =
79*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	"smc91111.c:v1.0 04/25/01 by Daris A Nevil (dnevil@snmc.com)\n";
80*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
81*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
82*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Autonegotiation timeout in seconds */
83*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SMC_AUTONEG_TIMEOUT
84*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SMC_AUTONEG_TIMEOUT 10
85*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
86*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
87*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------------------
88*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
89*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Configuration options, for the experienced user to change.
90*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
91*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  -------------------------------------------------------------------------*/
92*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
93*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
94*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Wait time for memory to be free.  This probably shouldn't be
95*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . tuned that much, as waiting for this means nothing else happens
96*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . in the system
97*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
98*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define MEMORY_WAIT_TIME 16
99*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
100*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
101*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if (SMC_DEBUG > 2 )
102*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK3(args...) printf(args)
103*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
104*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK3(args...)
105*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
106*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
107*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if SMC_DEBUG > 1
108*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK2(args...) printf(args)
109*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
110*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK2(args...)
111*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
112*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
113*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef SMC_DEBUG
114*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK(args...) printf(args)
115*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
116*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define PRINTK(args...)
117*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
118*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
119*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
120*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------------------
121*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
122*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . The internal workings of the driver.	 If you are changing anything
123*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . here with the SMC stuff, you should have the datasheet and know
124*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . what you are doing.
125*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
126*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  -------------------------------------------------------------------------*/
127*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CARDNAME "LAN91C111"
128*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
129*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Memory sizing constant */
130*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define LAN91C111_MEMORY_MULTIPLIER	(1024*2)
131*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
132*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SMC91111_BASE
133*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define CONFIG_SMC91111_BASE 0x20000300
134*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
135*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
136*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE
137*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
138*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SMC_DEV_NAME "SMC91111"
139*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SMC_PHY_ADDR 0x0000
140*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SMC_ALLOC_MAX_TRY 5
141*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SMC_TX_TIMEOUT 30
142*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
143*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define SMC_PHY_CLOCK_DELAY 1000
144*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
145*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define ETH_ZLEN 60
146*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
147*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef	CONFIG_SMC_USE_32_BIT
148*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define USE_32_BIT  1
149*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
150*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #undef USE_32_BIT
151*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
152*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*-----------------------------------------------------------------
153*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
154*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .  The driver can be entered at any of the following entry points.
155*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
156*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .------------------------------------------------------------------  */
157*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
158*2439e4bfSJean-Christophe PLAGNIOL-VILLARD extern int eth_init(bd_t *bd);
159*2439e4bfSJean-Christophe PLAGNIOL-VILLARD extern void eth_halt(void);
160*2439e4bfSJean-Christophe PLAGNIOL-VILLARD extern int eth_rx(void);
161*2439e4bfSJean-Christophe PLAGNIOL-VILLARD extern int eth_send(volatile void *packet, int length);
162*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
163*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef SHARED_RESOURCES
164*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	extern void swap_to(int device_id);
165*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
166*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
167*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
168*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . This is called by  register_netdev().  It is responsible for
169*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . checking the portlist for the SMC9000 series chipset.  If it finds
170*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . one, then it will initialize the device, find the hardware information,
171*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . and sets up the appropriate device parameters.
172*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . NOTE: Interrupts are *OFF* when this procedure is called.
173*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
174*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . NB:This shouldn't be static since it is referred to externally.
175*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
176*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int smc_init(void);
177*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
178*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
179*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . This is called by  unregister_netdev().  It is responsible for
180*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . cleaning up before the driver is finally unregistered and discarded.
181*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
182*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void smc_destructor(void);
183*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
184*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
185*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . The kernel calls this function when someone wants to use the device,
186*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . typically 'ifconfig ethX up'.
187*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
188*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_open(bd_t *bd);
189*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
190*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
191*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
192*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . This is called by the kernel in response to 'ifconfig ethX down'.  It
193*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . is responsible for cleaning up everything that the open routine
194*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . does, and maybe putting the card into a powerdown state.
195*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
196*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_close(void);
197*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
198*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
199*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Configures the PHY through the MII Management interface
200*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
201*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SMC91111_EXT_PHY
202*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_phy_configure(void);
203*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* !CONFIG_SMC91111_EXT_PHY */
204*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
205*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
206*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . This is a separate procedure to handle the receipt of a packet, to
207*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . leave the interrupt code looking slightly cleaner
208*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
209*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_rcv(void);
210*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
211*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* See if a MAC address is defined in the current environment. If so use it. If not
212*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . print a warning and set the environment and other globals with the default.
213*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . If an EEPROM is present it really should be consulted.
214*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
215*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int smc_get_ethaddr(bd_t *bd);
216*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int get_rom_mac(uchar *v_rom_mac);
217*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
218*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
219*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  ------------------------------------------------------------
220*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
221*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Internal routines
222*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
223*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  ------------------------------------------------------------
224*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
225*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
226*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SMC_USE_IOFUNCS
227*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
228*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * input and output functions
229*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
230*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Implemented due to inx,outx macros accessing the device improperly
231*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * and putting the device into an unkown state.
232*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
233*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * For instance, on Sharp LPD7A400 SDK, affects were chip memory
234*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * could not be free'd (hence the alloc failures), duplicate packets,
235*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * packets being corrupt (shifted) on the wire, etc.  Switching to the
236*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * inx,outx functions fixed this problem.
237*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
238*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline word SMC_inw(dword offset);
239*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void SMC_outw(word value, dword offset);
240*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline byte SMC_inb(dword offset);
241*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void SMC_outb(byte value, dword offset);
242*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void SMC_insw(dword offset, volatile uchar* buf, dword len);
243*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void SMC_outsw(dword offset, uchar* buf, dword len);
244*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
245*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define barrier() __asm__ __volatile__("": : :"memory")
246*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
247*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline word SMC_inw(dword offset)
248*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
249*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word v;
250*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	v = *((volatile word*)(SMC_BASE_ADDRESS+offset));
251*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	barrier(); *(volatile u32*)(0xc0000000);
252*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return v;
253*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
254*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
255*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void SMC_outw(word value, dword offset)
256*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
257*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	*((volatile word*)(SMC_BASE_ADDRESS+offset)) = value;
258*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	barrier(); *(volatile u32*)(0xc0000000);
259*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
260*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
261*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline byte SMC_inb(dword offset)
262*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
263*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word  _w;
264*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
265*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	_w = SMC_inw(offset & ~((dword)1));
266*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return (offset & 1) ? (byte)(_w >> 8) : (byte)(_w);
267*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
268*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
269*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void SMC_outb(byte value, dword offset)
270*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
271*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word  _w;
272*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
273*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	_w = SMC_inw(offset & ~((dword)1));
274*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (offset & 1)
275*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			*((volatile word*)(SMC_BASE_ADDRESS+(offset & ~((dword)1)))) = (value<<8) | (_w & 0x00ff);
276*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	else
277*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			*((volatile word*)(SMC_BASE_ADDRESS+offset)) = value | (_w & 0xff00);
278*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
279*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
280*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void SMC_insw(dword offset, volatile uchar* buf, dword len)
281*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
282*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	volatile word *p = (volatile word *)buf;
283*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
284*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while (len-- > 0) {
285*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		*p++ = SMC_inw(offset);
286*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		barrier();
287*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		*((volatile u32*)(0xc0000000));
288*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
289*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
290*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
291*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void SMC_outsw(dword offset, uchar* buf, dword len)
292*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
293*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	volatile word *p = (volatile word *)buf;
294*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
295*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while (len-- > 0) {
296*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw(*p++, offset);
297*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		barrier();
298*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		*(volatile u32*)(0xc0000000);
299*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
300*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
301*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif  /* CONFIG_SMC_USE_IOFUNCS */
302*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
303*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static char unsigned smc_mac_addr[6] = {0x02, 0x80, 0xad, 0x20, 0x31, 0xb8};
304*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
305*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
306*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * This function must be called before smc_open() if you want to override
307*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * the default mac address.
308*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
309*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
310*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void smc_set_mac_addr(const unsigned char *addr) {
311*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
312*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
313*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i=0; i < sizeof(smc_mac_addr); i++){
314*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		smc_mac_addr[i] = addr[i];
315*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
316*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
317*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
318*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
319*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * smc_get_macaddr is no longer used. If you want to override the default
320*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * mac address, call smc_get_mac_addr as a part of the board initialization.
321*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
322*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
323*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0
324*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void smc_get_macaddr( byte *addr ) {
325*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* MAC ADDRESS AT FLASHBLOCK 1 / OFFSET 0x10 */
326*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned char *dnp1110_mac = (unsigned char *) (0xE8000000 + 0x20010);
327*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
328*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
329*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
330*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i=0; i<6; i++) {
331*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	    addr[0] = *(dnp1110_mac+0);
332*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	    addr[1] = *(dnp1110_mac+1);
333*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	    addr[2] = *(dnp1110_mac+2);
334*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	    addr[3] = *(dnp1110_mac+3);
335*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	    addr[4] = *(dnp1110_mac+4);
336*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	    addr[5] = *(dnp1110_mac+5);
337*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
338*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
339*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* 0 */
340*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
341*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /***********************************************
342*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Show available memory		       *
343*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  ***********************************************/
344*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void dump_memory_info(void)
345*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
346*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word mem_info;
347*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word old_bank;
348*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
349*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	old_bank = SMC_inw(BANK_SELECT)&0xF;
350*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
351*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK(0);
352*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mem_info = SMC_inw( MIR_REG );
353*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2("Memory: %4d available\n", (mem_info >> 8)*2048);
354*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
355*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK(old_bank);
356*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
357*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
358*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . A rather simple routine to print out a packet for debugging purposes.
359*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
360*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if SMC_DEBUG > 2
361*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void print_packet( byte *, int );
362*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
363*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
364*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #define tx_done(dev) 1
365*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
366*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
367*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* this does a soft reset on the device */
368*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_reset( void );
369*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
370*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Enable Interrupts, Receive, and Transmit */
371*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_enable( void );
372*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
373*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* this puts the device in an inactive state */
374*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_shutdown( void );
375*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
376*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Routines to Read and Write the PHY Registers across the
377*2439e4bfSJean-Christophe PLAGNIOL-VILLARD    MII Management Interface
378*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
379*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
380*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SMC91111_EXT_PHY
381*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static word smc_read_phy_register(byte phyreg);
382*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_write_phy_register(byte phyreg, word phydata);
383*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* !CONFIG_SMC91111_EXT_PHY */
384*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
385*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
386*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int poll4int (byte mask, int timeout)
387*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
388*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int tmo = get_timer (0) + timeout * CFG_HZ;
389*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int is_timeout = 0;
390*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word old_bank = SMC_inw (BSR_REG);
391*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
392*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2 ("Polling...\n");
393*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (2);
394*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while ((SMC_inw (SMC91111_INT_REG) & mask) == 0) {
395*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (get_timer (0) >= tmo) {
396*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			is_timeout = 1;
397*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
398*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
399*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
400*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
401*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* restore old bank selection */
402*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (old_bank);
403*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
404*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (is_timeout)
405*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 1;
406*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	else
407*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
408*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
409*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
410*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Only one release command at a time, please */
411*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static inline void smc_wait_mmu_release_complete (void)
412*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
413*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int count = 0;
414*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
415*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* assume bank 2 selected */
416*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while (SMC_inw (MMU_CMD_REG) & MC_BUSY) {
417*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay (1);	/* Wait until not busy */
418*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (++count > 200)
419*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
420*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
421*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
422*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
423*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
424*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Function: smc_reset( void )
425*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Purpose:
426*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	This sets the SMC91111 chip to its normal state, hopefully from whatever
427*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	mess that any other DOS driver has put it in.
428*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
429*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Maybe I should reset more registers to defaults in here?  SOFTRST  should
430*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . do that for me.
431*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
432*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Method:
433*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	1.  send a SOFT RESET
434*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	2.  wait for it to finish
435*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	3.  enable autorelease mode
436*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	4.  reset the memory management unit
437*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	5.  clear all interrupts
438*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
439*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
440*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_reset (void)
441*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
442*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2 ("%s: smc_reset\n", SMC_DEV_NAME);
443*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
444*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* This resets the registers mostly to defaults, but doesn't
445*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   affect EEPROM.  That seems unnecessary */
446*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (0);
447*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (RCR_SOFTRST, RCR_REG);
448*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
449*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Setup the Configuration Register */
450*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* This is necessary because the CONFIG_REG is not affected */
451*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* by a soft reset */
452*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
453*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (1);
454*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_SMC91111_EXT_PHY)
455*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (CONFIG_DEFAULT | CONFIG_EXT_PHY, CONFIG_REG);
456*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
457*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (CONFIG_DEFAULT, CONFIG_REG);
458*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
459*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
460*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
461*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Release from possible power-down state */
462*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Configuration register is not affected by Soft Reset */
463*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (SMC_inw (CONFIG_REG) | CONFIG_EPH_POWER_EN, CONFIG_REG);
464*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
465*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (0);
466*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
467*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* this should pause enough for the chip to be happy */
468*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay (10);
469*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
470*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Disable transmit and receive functionality */
471*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (RCR_CLEAR, RCR_REG);
472*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (TCR_CLEAR, TCR_REG);
473*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
474*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* set the control register */
475*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (1);
476*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (CTL_DEFAULT, CTL_REG);
477*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
478*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Reset the MMU */
479*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (2);
480*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_wait_mmu_release_complete ();
481*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (MC_RESET, MMU_CMD_REG);
482*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while (SMC_inw (MMU_CMD_REG) & MC_BUSY)
483*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay (1);	/* Wait until not busy */
484*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
485*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Note:  It doesn't seem that waiting for the MMU busy is needed here,
486*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   but this is a place where future chipsets _COULD_ break.  Be wary
487*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   of issuing another MMU command right after this */
488*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
489*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Disable all interrupts */
490*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outb (0, IM_REG);
491*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
492*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
493*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
494*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Function: smc_enable
495*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Purpose: let the chip talk to the outside work
496*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Method:
497*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	1.  Enable the transmitter
498*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	2.  Enable the receiver
499*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	3.  Enable interrupts
500*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
501*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_enable()
502*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
503*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2("%s: smc_enable\n", SMC_DEV_NAME);
504*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK( 0 );
505*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* see the header file for options in TCR/RCR DEFAULT*/
506*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw( TCR_DEFAULT, TCR_REG );
507*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw( RCR_DEFAULT, RCR_REG );
508*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
509*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* clear MII_DIS */
510*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*	smc_write_phy_register(PHY_CNTL_REG, 0x0000); */
511*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
512*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
513*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
514*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Function: smc_shutdown
515*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Purpose:  closes down the SMC91xxx chip.
516*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Method:
517*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	1. zero the interrupt mask
518*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	2. clear the enable receive flag
519*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	3. clear the enable xmit flags
520*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
521*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . TODO:
522*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .   (1) maybe utilize power down mode.
523*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Why not yet?  Because while the chip will go into power down mode,
524*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	the manual says that it will wake up in response to any I/O requests
525*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	in the register space.	 Empirical results do not show this working.
526*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
527*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_shutdown()
528*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
529*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2(CARDNAME ": smc_shutdown\n");
530*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
531*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* no more interrupts for me */
532*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK( 2 );
533*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outb( 0, IM_REG );
534*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
535*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* and tell the card to stay away from that nasty outside world */
536*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK( 0 );
537*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outb( RCR_CLEAR, RCR_REG );
538*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outb( TCR_CLEAR, TCR_REG );
539*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef SHARED_RESOURCES
540*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	swap_to(FLASH);
541*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
542*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
543*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
544*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
545*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
546*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Function:  smc_hardware_send_packet(struct net_device * )
547*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Purpose:
548*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	This sends the actual packet to the SMC9xxx chip.
549*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
550*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Algorithm:
551*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	First, see if a saved_skb is available.
552*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .		( this should NOT be called if there is no 'saved_skb'
553*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Now, find the packet number that the chip allocated
554*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Point the data pointers at it in memory
555*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Set the length word in the chip's memory
556*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Dump the packet to chip memory
557*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Check if a last byte is needed ( odd length packet )
558*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .		if so, set the control flag right
559*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Tell the card to send it
560*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Enable the transmit interrupt, so I know if it failed
561*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .	Free the kernel data if I actually sent it.
562*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
563*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_send_packet (volatile void *packet, int packet_length)
564*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
565*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte packet_no;
566*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned long ioaddr;
567*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte *buf;
568*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int length;
569*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int numPages;
570*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int try = 0;
571*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int time_out;
572*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte status;
573*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte saved_pnr;
574*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word saved_ptr;
575*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
576*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* save PTR and PNR registers before manipulation */
577*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (2);
578*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	saved_pnr = SMC_inb( PN_REG );
579*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	saved_ptr = SMC_inw( PTR_REG );
580*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
581*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK3 ("%s: smc_hardware_send_packet\n", SMC_DEV_NAME);
582*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
583*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN;
584*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
585*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* allocate memory
586*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 ** The MMU wants the number of pages to be the number of 256 bytes
587*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
588*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 **
589*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 ** The 91C111 ignores the size bits, but the code is left intact
590*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 ** for backwards and future compatibility.
591*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 **
592*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 ** Pkt size for allocating is data length +6 (for additional status
593*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 ** words, length and ctl!)
594*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 **
595*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 ** If odd size then last byte is included in this header.
596*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 */
597*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	numPages = ((length & 0xfffe) + 6);
598*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	numPages >>= 8;		/* Divide by 256 */
599*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
600*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (numPages > 7) {
601*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Far too big packet error. \n", SMC_DEV_NAME);
602*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
603*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
604*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
605*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* now, try to allocate the memory */
606*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (2);
607*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (MC_ALLOC | numPages, MMU_CMD_REG);
608*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
609*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* FIXME: the ALLOC_INT bit never gets set *
610*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * so the following will always give a	   *
611*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * memory allocation error.		   *
612*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * same code works in armboot though	   *
613*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * -ro
614*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 */
615*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
616*2439e4bfSJean-Christophe PLAGNIOL-VILLARD again:
617*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	try++;
618*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	time_out = MEMORY_WAIT_TIME;
619*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	do {
620*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		status = SMC_inb (SMC91111_INT_REG);
621*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (status & IM_ALLOC_INT) {
622*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			/* acknowledge the interrupt */
623*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			SMC_outb (IM_ALLOC_INT, SMC91111_INT_REG);
624*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
625*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
626*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} while (--time_out);
627*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
628*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (!time_out) {
629*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		PRINTK2 ("%s: memory allocation, try %d failed ...\n",
630*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			 SMC_DEV_NAME, try);
631*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (try < SMC_ALLOC_MAX_TRY)
632*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			goto again;
633*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
634*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			return 0;
635*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
636*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
637*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2 ("%s: memory allocation, try %d succeeded ...\n",
638*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		 SMC_DEV_NAME, try);
639*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
640*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* I can send the packet now.. */
641*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
642*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	ioaddr = SMC_BASE_ADDRESS;
643*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
644*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	buf = (byte *) packet;
645*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
646*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* If I get here, I _know_ there is a packet slot waiting for me */
647*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	packet_no = SMC_inb (AR_REG);
648*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (packet_no & AR_FAILED) {
649*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* or isn't there?  BAD CHIP! */
650*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: Memory allocation failed. \n", SMC_DEV_NAME);
651*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
652*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
653*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
654*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* we have a packet address, so tell the card to use it */
655*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_XAENIAX
656*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outb (packet_no, PN_REG);
657*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
658*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* On Xaeniax board, we can't use SMC_outb here because that way
659*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * the Allocate MMU command will end up written to the command register
660*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * as well, which will lead to a problem.
661*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 */
662*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outl (packet_no << 16, 0);
663*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
664*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* do not write new ptr value if Write data fifo not empty */
665*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while ( saved_ptr & PTR_NOTEMPTY )
666*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("Write data fifo not empty!\n");
667*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
668*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* point to the beginning of the packet */
669*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (PTR_AUTOINC, PTR_REG);
670*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
671*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK3 ("%s: Trying to xmit packet of length %x\n",
672*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		 SMC_DEV_NAME, length);
673*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
674*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if SMC_DEBUG > 2
675*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf ("Transmitting Packet\n");
676*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	print_packet (buf, length);
677*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
678*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
679*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* send the packet length ( +6 for status, length and ctl byte )
680*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   and the status word ( set to zeros ) */
681*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef USE_32_BIT
682*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outl ((length + 6) << 16, SMC91111_DATA_REG);
683*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
684*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (0, SMC91111_DATA_REG);
685*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* send the packet length ( +6 for status words, length, and ctl */
686*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw ((length + 6), SMC91111_DATA_REG);
687*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
688*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
689*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* send the actual data
690*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   . I _think_ it's faster to send the longs first, and then
691*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   . mop up by sending the last word.  It depends heavily
692*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   . on alignment, at least on the 486.	 Maybe it would be
693*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   . a good idea to check which is optimal?  But that could take
694*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	   . almost as much time as is saved?
695*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 */
696*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef USE_32_BIT
697*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outsl (SMC91111_DATA_REG, buf, length >> 2);
698*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_XAENIAX
699*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (length & 0x2)
700*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (*((word *) (buf + (length & 0xFFFFFFFC))),
701*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			  SMC91111_DATA_REG);
702*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
703*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* On XANEIAX, we can only use 32-bit writes, so we need to handle
704*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * unaligned tail part specially. The standard code doesn't work.
705*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 */
706*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((length & 3) == 3) {
707*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		u16 * ptr = (u16*) &buf[length-3];
708*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outl((*ptr) | ((0x2000 | buf[length-1]) << 16),
709*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				SMC91111_DATA_REG);
710*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else if ((length & 2) == 2) {
711*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		u16 * ptr = (u16*) &buf[length-2];
712*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outl(*ptr, SMC91111_DATA_REG);
713*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else if (length & 1) {
714*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outl((0x2000 | buf[length-1]), SMC91111_DATA_REG);
715*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else {
716*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outl(0, SMC91111_DATA_REG);
717*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
718*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
719*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
720*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outsw (SMC91111_DATA_REG, buf, (length) >> 1);
721*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* USE_32_BIT */
722*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
723*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_XAENIAX
724*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Send the last byte, if there is one.	  */
725*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((length & 1) == 0) {
726*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (0, SMC91111_DATA_REG);
727*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else {
728*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (buf[length - 1] | 0x2000, SMC91111_DATA_REG);
729*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
730*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
731*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
732*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* and let the chipset deal with it */
733*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (MC_ENQUEUE, MMU_CMD_REG);
734*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
735*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* poll for TX INT */
736*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* if (poll4int (IM_TX_INT, SMC_TX_TIMEOUT)) { */
737*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* poll for TX_EMPTY INT - autorelease enabled */
738*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (poll4int(IM_TX_EMPTY_INT, SMC_TX_TIMEOUT)) {
739*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* sending failed */
740*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		PRINTK2 ("%s: TX timeout, sending failed...\n", SMC_DEV_NAME);
741*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
742*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* release packet */
743*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* no need to release, MMU does that now */
744*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_XAENIAX
745*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		 SMC_outw (MC_FREEPKT, MMU_CMD_REG);
746*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
747*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
748*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* wait for MMU getting ready (low) */
749*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		while (SMC_inw (MMU_CMD_REG) & MC_BUSY) {
750*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			udelay (10);
751*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
752*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
753*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		PRINTK2 ("MMU ready\n");
754*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
755*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
756*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
757*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else {
758*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* ack. int */
759*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outb (IM_TX_EMPTY_INT, SMC91111_INT_REG);
760*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* SMC_outb (IM_TX_INT, SMC91111_INT_REG); */
761*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		PRINTK2 ("%s: Sent packet of length %d \n", SMC_DEV_NAME,
762*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			 length);
763*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
764*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* release packet */
765*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* no need to release, MMU does that now */
766*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_XAENIAX
767*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (MC_FREEPKT, MMU_CMD_REG);
768*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
769*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
770*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* wait for MMU getting ready (low) */
771*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		while (SMC_inw (MMU_CMD_REG) & MC_BUSY) {
772*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			udelay (10);
773*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
774*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
775*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		PRINTK2 ("MMU ready\n");
776*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
777*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
778*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
779*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
780*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* restore previously saved registers */
781*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_XAENIAX
782*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outb( saved_pnr, PN_REG );
783*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
784*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* On Xaeniax board, we can't use SMC_outb here because that way
785*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * the Allocate MMU command will end up written to the command register
786*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * as well, which will lead to a problem.
787*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 */
788*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outl(saved_pnr << 16, 0);
789*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
790*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw( saved_ptr, PTR_REG );
791*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
792*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return length;
793*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
794*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
795*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*-------------------------------------------------------------------------
796*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  |
797*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  | smc_destructor( struct net_device * dev )
798*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  |   Input parameters:
799*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  |	dev, pointer to the device structure
800*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  |
801*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  |   Output:
802*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  |	None.
803*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  |
804*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  ---------------------------------------------------------------------------
805*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
806*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void smc_destructor()
807*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
808*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2(CARDNAME ": smc_destructor\n");
809*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
810*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
811*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
812*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
813*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Open and Initialize the board
814*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
815*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  * Set up everything, reset the card, etc ..
816*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  *
817*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  */
818*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_open (bd_t * bd)
819*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
820*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i, err;
821*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
822*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2 ("%s: smc_open\n", SMC_DEV_NAME);
823*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
824*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* reset the hardware */
825*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_reset ();
826*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_enable ();
827*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
828*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Configure the PHY */
829*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SMC91111_EXT_PHY
830*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_phy_configure ();
831*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
832*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
833*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* conservative setting (10Mbps, HalfDuplex, no AutoNeg.) */
834*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*	SMC_SELECT_BANK(0); */
835*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*	SMC_outw(0, RPC_REG); */
836*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (1);
837*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
838*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	err = smc_get_ethaddr (bd);	/* set smc_mac_addr, and sync it with u-boot globals */
839*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (err < 0) {
840*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		memset (bd->bi_enetaddr, 0, 6); /* hack to make error stick! upper code will abort if not set */
841*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return (-1);	/* upper code ignores this, but NOT bi_enetaddr */
842*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
843*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef USE_32_BIT
844*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 6; i += 2) {
845*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		word address;
846*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
847*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		address = smc_mac_addr[i + 1] << 8;
848*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		address |= smc_mac_addr[i];
849*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (address, (ADDR0_REG + i));
850*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
851*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
852*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 6; i++)
853*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outb (smc_mac_addr[i], (ADDR0_REG + i));
854*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
855*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
856*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
857*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
858*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
859*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*-------------------------------------------------------------
860*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
861*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . smc_rcv -  receive a packet from the card
862*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
863*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . There is ( at least ) a packet waiting to be read from
864*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . chip-memory.
865*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
866*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . o Read the status
867*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . o If an error, record it
868*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . o otherwise, read in the packet
869*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  --------------------------------------------------------------
870*2439e4bfSJean-Christophe PLAGNIOL-VILLARD */
871*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_rcv()
872*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
873*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int	packet_number;
874*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word	status;
875*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word	packet_length;
876*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int	is_error = 0;
877*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef USE_32_BIT
878*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	dword stat_len;
879*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
880*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte saved_pnr;
881*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word saved_ptr;
882*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
883*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK(2);
884*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* save PTR and PTR registers */
885*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	saved_pnr = SMC_inb( PN_REG );
886*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	saved_ptr = SMC_inw( PTR_REG );
887*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
888*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	packet_number = SMC_inw( RXFIFO_REG );
889*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
890*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ( packet_number & RXFIFO_REMPTY ) {
891*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
892*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
893*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
894*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
895*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK3("%s: smc_rcv\n", SMC_DEV_NAME);
896*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/*  start reading from the start of the packet */
897*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw( PTR_READ | PTR_RCV | PTR_AUTOINC, PTR_REG );
898*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
899*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* First two words are status and packet_length */
900*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef USE_32_BIT
901*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	stat_len = SMC_inl(SMC91111_DATA_REG);
902*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	status = stat_len & 0xffff;
903*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	packet_length = stat_len >> 16;
904*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
905*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	status		= SMC_inw( SMC91111_DATA_REG );
906*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	packet_length	= SMC_inw( SMC91111_DATA_REG );
907*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
908*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
909*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	packet_length &= 0x07ff;  /* mask off top bits */
910*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
911*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2("RCV: STATUS %4x LENGTH %4x\n", status, packet_length );
912*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
913*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ( !(status & RS_ERRORS ) ){
914*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Adjust for having already read the first two words */
915*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		packet_length -= 4; /*4; */
916*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
917*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
918*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* set odd length for bug in LAN91C111, */
919*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* which never sets RS_ODDFRAME */
920*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* TODO ? */
921*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
922*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
923*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef USE_32_BIT
924*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		PRINTK3(" Reading %d dwords (and %d bytes) \n",
925*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			packet_length >> 2, packet_length & 3 );
926*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* QUESTION:  Like in the TX routine, do I want
927*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		   to send the DWORDs or the bytes first, or some
928*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		   mixture.  A mixture might improve already slow PIO
929*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		   performance	*/
930*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_insl( SMC91111_DATA_REG , NetRxPackets[0], packet_length >> 2 );
931*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* read the left over bytes */
932*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (packet_length & 3) {
933*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			int i;
934*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
935*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			byte *tail = (byte *)(NetRxPackets[0] + (packet_length & ~3));
936*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			dword leftover = SMC_inl(SMC91111_DATA_REG);
937*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			for (i=0; i<(packet_length & 3); i++)
938*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				*tail++ = (byte) (leftover >> (8*i)) & 0xff;
939*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
940*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
941*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		PRINTK3(" Reading %d words and %d byte(s) \n",
942*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			(packet_length >> 1 ), packet_length & 1 );
943*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_insw(SMC91111_DATA_REG , NetRxPackets[0], packet_length >> 1);
944*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
945*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* USE_32_BIT */
946*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
947*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if	SMC_DEBUG > 2
948*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("Receiving Packet\n");
949*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		print_packet( NetRxPackets[0], packet_length );
950*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
951*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else {
952*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* error ... */
953*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* TODO ? */
954*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		is_error = 1;
955*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
956*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
957*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY )
958*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(1); /* Wait until not busy */
959*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
960*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/*  error or good, tell the card to get rid of this packet */
961*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw( MC_RELEASE, MMU_CMD_REG );
962*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
963*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while ( SMC_inw( MMU_CMD_REG ) & MC_BUSY )
964*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(1); /* Wait until not busy */
965*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
966*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* restore saved registers */
967*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_XAENIAX
968*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outb( saved_pnr, PN_REG );
969*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
970*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* On Xaeniax board, we can't use SMC_outb here because that way
971*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * the Allocate MMU command will end up written to the command register
972*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 * as well, which will lead to a problem.
973*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	 */
974*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outl( saved_pnr << 16, 0);
975*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
976*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw( saved_ptr, PTR_REG );
977*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
978*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (!is_error) {
979*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Pass the packet up to the protocol layers. */
980*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		NetReceive(NetRxPackets[0], packet_length);
981*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return packet_length;
982*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else {
983*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
984*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
985*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
986*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
987*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
988*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
989*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------
990*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . smc_close
991*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
992*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . this makes the board clean up everything that it can
993*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . and not talk to the outside world.	Caused by
994*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . an 'ifconfig ethX down'
995*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .
996*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  -----------------------------------------------------*/
997*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_close()
998*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
999*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2("%s: smc_close\n", SMC_DEV_NAME);
1000*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1001*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* clear everything */
1002*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_shutdown();
1003*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1004*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
1005*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1006*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1007*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1008*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if 0
1009*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1010*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Modify a bit in the LAN91C111 register set
1011*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1012*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static word smc_modify_regbit(int bank, int ioaddr, int reg,
1013*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned int bit, int val)
1014*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1015*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word regval;
1016*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1017*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK( bank );
1018*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1019*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	regval = SMC_inw( reg );
1020*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (val)
1021*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		regval |= bit;
1022*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	else
1023*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		regval &= ~bit;
1024*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1025*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw( regval, 0 );
1026*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return(regval);
1027*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1028*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1029*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1030*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1031*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Retrieve a bit in the LAN91C111 register set
1032*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1033*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_get_regbit(int bank, int ioaddr, int reg, unsigned int bit)
1034*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1035*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK( bank );
1036*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ( SMC_inw( reg ) & bit)
1037*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return(1);
1038*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	else
1039*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return(0);
1040*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1041*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1042*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1043*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1044*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Modify a LAN91C111 register (word access only)
1045*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1046*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_modify_reg(int bank, int ioaddr, int reg, word val)
1047*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1048*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK( bank );
1049*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw( val, reg );
1050*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1051*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1052*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1053*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1054*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Retrieve a LAN91C111 register (word access only)
1055*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1056*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static int smc_get_reg(int bank, int ioaddr, int reg)
1057*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1058*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK( bank );
1059*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return(SMC_inw( reg ));
1060*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1061*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1062*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* 0 */
1063*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1064*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*---PHY CONTROL AND CONFIGURATION----------------------------------------- */
1065*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1066*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if (SMC_DEBUG > 2 )
1067*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1068*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1069*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Debugging function for viewing MII Management serial bitstream
1070*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1071*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_dump_mii_stream (byte * bits, int size)
1072*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1073*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
1074*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1075*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf ("BIT#:");
1076*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < size; ++i) {
1077*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%d", i % 10);
1078*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1079*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1080*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf ("\nMDOE:");
1081*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < size; ++i) {
1082*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (bits[i] & MII_MDOE)
1083*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("1");
1084*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
1085*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("0");
1086*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1087*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1088*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf ("\nMDO :");
1089*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < size; ++i) {
1090*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (bits[i] & MII_MDO)
1091*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("1");
1092*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
1093*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("0");
1094*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1095*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1096*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf ("\nMDI :");
1097*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < size; ++i) {
1098*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (bits[i] & MII_MDI)
1099*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("1");
1100*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
1101*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("0");
1102*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1103*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1104*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf ("\n");
1105*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1106*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
1107*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1108*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1109*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Reads a register from the MII Management serial interface
1110*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1111*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SMC91111_EXT_PHY
1112*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static word smc_read_phy_register (byte phyreg)
1113*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1114*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int oldBank;
1115*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
1116*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte mask;
1117*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word mii_reg;
1118*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte bits[64];
1119*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int clk_idx = 0;
1120*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int input_idx;
1121*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word phydata;
1122*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte phyaddr = SMC_PHY_ADDR;
1123*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1124*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* 32 consecutive ones on MDO to establish sync */
1125*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 32; ++i)
1126*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		bits[clk_idx++] = MII_MDOE | MII_MDO;
1127*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1128*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Start code <01> */
1129*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = MII_MDOE;
1130*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = MII_MDOE | MII_MDO;
1131*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1132*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Read command <10> */
1133*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = MII_MDOE | MII_MDO;
1134*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = MII_MDOE;
1135*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1136*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Output the PHY address, msb first */
1137*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mask = (byte) 0x10;
1138*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 5; ++i) {
1139*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (phyaddr & mask)
1140*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE | MII_MDO;
1141*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
1142*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE;
1143*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1144*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Shift to next lowest bit */
1145*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		mask >>= 1;
1146*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1147*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1148*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Output the phy register number, msb first */
1149*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mask = (byte) 0x10;
1150*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 5; ++i) {
1151*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (phyreg & mask)
1152*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE | MII_MDO;
1153*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
1154*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE;
1155*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1156*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Shift to next lowest bit */
1157*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		mask >>= 1;
1158*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1159*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1160*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Tristate and turnaround (2 bit times) */
1161*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = 0;
1162*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/*bits[clk_idx++] = 0; */
1163*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1164*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Input starts at this bit time */
1165*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	input_idx = clk_idx;
1166*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1167*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Will input 16 bits */
1168*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 16; ++i)
1169*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		bits[clk_idx++] = 0;
1170*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1171*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Final clock bit */
1172*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = 0;
1173*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1174*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Save the current bank */
1175*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	oldBank = SMC_inw (BANK_SELECT);
1176*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1177*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Select bank 3 */
1178*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (3);
1179*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1180*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Get the current MII register value */
1181*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mii_reg = SMC_inw (MII_REG);
1182*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1183*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Turn off all MII Interface bits */
1184*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO);
1185*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1186*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Clock all 64 cycles */
1187*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < sizeof bits; ++i) {
1188*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Clock Low - output data */
1189*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (mii_reg | bits[i], MII_REG);
1190*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay (SMC_PHY_CLOCK_DELAY);
1191*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1192*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1193*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Clock Hi - input data */
1194*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (mii_reg | bits[i] | MII_MCLK, MII_REG);
1195*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay (SMC_PHY_CLOCK_DELAY);
1196*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		bits[i] |= SMC_inw (MII_REG) & MII_MDI;
1197*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1198*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1199*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Return to idle state */
1200*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Set clock to low, data to low, and output tristated */
1201*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (mii_reg, MII_REG);
1202*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay (SMC_PHY_CLOCK_DELAY);
1203*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1204*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Restore original bank select */
1205*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (oldBank);
1206*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1207*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Recover input data */
1208*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	phydata = 0;
1209*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 16; ++i) {
1210*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		phydata <<= 1;
1211*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1212*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (bits[input_idx++] & MII_MDI)
1213*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			phydata |= 0x0001;
1214*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1215*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1216*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if (SMC_DEBUG > 2 )
1217*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf ("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
1218*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		phyaddr, phyreg, phydata);
1219*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_dump_mii_stream (bits, sizeof bits);
1220*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
1221*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1222*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return (phydata);
1223*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1224*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1225*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1226*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1227*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Writes a register to the MII Management serial interface
1228*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1229*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_write_phy_register (byte phyreg, word phydata)
1230*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1231*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int oldBank;
1232*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
1233*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word mask;
1234*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word mii_reg;
1235*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte bits[65];
1236*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int clk_idx = 0;
1237*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte phyaddr = SMC_PHY_ADDR;
1238*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1239*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* 32 consecutive ones on MDO to establish sync */
1240*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 32; ++i)
1241*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		bits[clk_idx++] = MII_MDOE | MII_MDO;
1242*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1243*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Start code <01> */
1244*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = MII_MDOE;
1245*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = MII_MDOE | MII_MDO;
1246*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1247*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Write command <01> */
1248*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = MII_MDOE;
1249*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = MII_MDOE | MII_MDO;
1250*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1251*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Output the PHY address, msb first */
1252*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mask = (byte) 0x10;
1253*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 5; ++i) {
1254*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (phyaddr & mask)
1255*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE | MII_MDO;
1256*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
1257*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE;
1258*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1259*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Shift to next lowest bit */
1260*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		mask >>= 1;
1261*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1262*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1263*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Output the phy register number, msb first */
1264*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mask = (byte) 0x10;
1265*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 5; ++i) {
1266*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (phyreg & mask)
1267*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE | MII_MDO;
1268*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
1269*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE;
1270*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1271*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Shift to next lowest bit */
1272*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		mask >>= 1;
1273*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1274*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1275*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Tristate and turnaround (2 bit times) */
1276*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = 0;
1277*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = 0;
1278*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1279*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Write out 16 bits of data, msb first */
1280*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mask = 0x8000;
1281*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < 16; ++i) {
1282*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (phydata & mask)
1283*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE | MII_MDO;
1284*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		else
1285*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			bits[clk_idx++] = MII_MDOE;
1286*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1287*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Shift to next lowest bit */
1288*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		mask >>= 1;
1289*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1290*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1291*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Final clock bit (tristate) */
1292*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	bits[clk_idx++] = 0;
1293*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1294*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Save the current bank */
1295*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	oldBank = SMC_inw (BANK_SELECT);
1296*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1297*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Select bank 3 */
1298*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (3);
1299*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1300*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Get the current MII register value */
1301*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mii_reg = SMC_inw (MII_REG);
1302*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1303*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Turn off all MII Interface bits */
1304*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	mii_reg &= ~(MII_MDOE | MII_MCLK | MII_MDI | MII_MDO);
1305*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1306*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Clock all cycles */
1307*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < sizeof bits; ++i) {
1308*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Clock Low - output data */
1309*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (mii_reg | bits[i], MII_REG);
1310*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay (SMC_PHY_CLOCK_DELAY);
1311*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1312*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1313*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Clock Hi - input data */
1314*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		SMC_outw (mii_reg | bits[i] | MII_MCLK, MII_REG);
1315*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay (SMC_PHY_CLOCK_DELAY);
1316*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		bits[i] |= SMC_inw (MII_REG) & MII_MDI;
1317*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1318*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1319*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Return to idle state */
1320*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Set clock to low, data to low, and output tristated */
1321*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (mii_reg, MII_REG);
1322*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay (SMC_PHY_CLOCK_DELAY);
1323*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1324*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Restore original bank select */
1325*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (oldBank);
1326*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1327*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if (SMC_DEBUG > 2 )
1328*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf ("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
1329*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		phyaddr, phyreg, phydata);
1330*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_dump_mii_stream (bits, sizeof bits);
1331*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
1332*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1333*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* !CONFIG_SMC91111_EXT_PHY */
1334*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1335*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1336*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1337*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Waits the specified number of milliseconds - kernel friendly
1338*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1339*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SMC91111_EXT_PHY
1340*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_wait_ms(unsigned int ms)
1341*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1342*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay(ms*1000);
1343*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1344*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* !CONFIG_SMC91111_EXT_PHY */
1345*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1346*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1347*2439e4bfSJean-Christophe PLAGNIOL-VILLARD /*------------------------------------------------------------
1348*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . Configures the specified PHY using Autonegotiation. Calls
1349*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  . smc_phy_fixed() if the user has requested a certain config.
1350*2439e4bfSJean-Christophe PLAGNIOL-VILLARD  .-------------------------------------------------------------*/
1351*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SMC91111_EXT_PHY
1352*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void smc_phy_configure ()
1353*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1354*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int timeout;
1355*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	byte phyaddr;
1356*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word my_phy_caps;	/* My PHY capabilities */
1357*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word my_ad_caps;	/* My Advertised capabilities */
1358*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	word status = 0;	/*;my status = 0 */
1359*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int failed = 0;
1360*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1361*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK3 ("%s: smc_program_phy()\n", SMC_DEV_NAME);
1362*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1363*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1364*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Get the detected phy address */
1365*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	phyaddr = SMC_PHY_ADDR;
1366*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1367*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Reset the PHY, setting all other bits to zero */
1368*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_write_phy_register (PHY_CNTL_REG, PHY_CNTL_RST);
1369*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1370*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Wait for the reset to complete, or time out */
1371*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	timeout = 6;		/* Wait up to 3 seconds */
1372*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while (timeout--) {
1373*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (!(smc_read_phy_register (PHY_CNTL_REG)
1374*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		      & PHY_CNTL_RST)) {
1375*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			/* reset complete */
1376*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
1377*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
1378*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1379*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		smc_wait_ms (500);	/* wait 500 millisecs */
1380*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1381*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1382*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (timeout < 1) {
1383*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s:PHY reset timed out\n", SMC_DEV_NAME);
1384*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		goto smc_phy_configure_exit;
1385*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1386*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1387*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Read PHY Register 18, Status Output */
1388*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* lp->lastPhy18 = smc_read_phy_register(PHY_INT_REG); */
1389*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1390*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Enable PHY Interrupts (for register 18) */
1391*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Interrupts listed here are disabled */
1392*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_write_phy_register (PHY_MASK_REG, 0xffff);
1393*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1394*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Configure the Receive/Phy Control register */
1395*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (0);
1396*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (RPC_DEFAULT, RPC_REG);
1397*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1398*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Copy our capabilities from PHY_STAT_REG to PHY_AD_REG */
1399*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	my_phy_caps = smc_read_phy_register (PHY_STAT_REG);
1400*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	my_ad_caps = PHY_AD_CSMA;	/* I am CSMA capable */
1401*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1402*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (my_phy_caps & PHY_STAT_CAP_T4)
1403*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		my_ad_caps |= PHY_AD_T4;
1404*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1405*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (my_phy_caps & PHY_STAT_CAP_TXF)
1406*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		my_ad_caps |= PHY_AD_TX_FDX;
1407*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1408*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (my_phy_caps & PHY_STAT_CAP_TXH)
1409*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		my_ad_caps |= PHY_AD_TX_HDX;
1410*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1411*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (my_phy_caps & PHY_STAT_CAP_TF)
1412*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		my_ad_caps |= PHY_AD_10_FDX;
1413*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1414*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (my_phy_caps & PHY_STAT_CAP_TH)
1415*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		my_ad_caps |= PHY_AD_10_HDX;
1416*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1417*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Update our Auto-Neg Advertisement Register */
1418*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_write_phy_register (PHY_AD_REG, my_ad_caps);
1419*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1420*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Read the register back.  Without this, it appears that when */
1421*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* auto-negotiation is restarted, sometimes it isn't ready and */
1422*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* the link does not come up. */
1423*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_read_phy_register(PHY_AD_REG);
1424*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1425*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2 ("%s: phy caps=%x\n", SMC_DEV_NAME, my_phy_caps);
1426*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK2 ("%s: phy advertised caps=%x\n", SMC_DEV_NAME, my_ad_caps);
1427*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1428*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Restart auto-negotiation process in order to advertise my caps */
1429*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_write_phy_register (PHY_CNTL_REG,
1430*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST);
1431*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1432*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Wait for the auto-negotiation to complete.  This may take from */
1433*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* 2 to 3 seconds. */
1434*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Wait for the reset to complete, or time out */
1435*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	timeout = CONFIG_SMC_AUTONEG_TIMEOUT * 2;
1436*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while (timeout--) {
1437*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1438*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		status = smc_read_phy_register (PHY_STAT_REG);
1439*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (status & PHY_STAT_ANEG_ACK) {
1440*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			/* auto-negotiate complete */
1441*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
1442*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
1443*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1444*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		smc_wait_ms (500);	/* wait 500 millisecs */
1445*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1446*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Restart auto-negotiation if remote fault */
1447*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (status & PHY_STAT_REM_FLT) {
1448*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("%s: PHY remote fault detected\n",
1449*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				SMC_DEV_NAME);
1450*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1451*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			/* Restart auto-negotiation */
1452*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("%s: PHY restarting auto-negotiation\n",
1453*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				SMC_DEV_NAME);
1454*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			smc_write_phy_register (PHY_CNTL_REG,
1455*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 						PHY_CNTL_ANEG_EN |
1456*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 						PHY_CNTL_ANEG_RST |
1457*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 						PHY_CNTL_SPEED |
1458*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 						PHY_CNTL_DPLX);
1459*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
1460*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1461*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1462*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (timeout < 1) {
1463*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: PHY auto-negotiate timed out\n", SMC_DEV_NAME);
1464*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		failed = 1;
1465*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1466*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1467*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Fail if we detected an auto-negotiate remote fault */
1468*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (status & PHY_STAT_REM_FLT) {
1469*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s: PHY remote fault detected\n", SMC_DEV_NAME);
1470*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		failed = 1;
1471*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1472*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1473*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Re-Configure the Receive/Phy Control register */
1474*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_outw (RPC_DEFAULT, RPC_REG);
1475*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1476*2439e4bfSJean-Christophe PLAGNIOL-VILLARD smc_phy_configure_exit:	;
1477*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1478*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1479*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* !CONFIG_SMC91111_EXT_PHY */
1480*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1481*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1482*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if SMC_DEBUG > 2
1483*2439e4bfSJean-Christophe PLAGNIOL-VILLARD static void print_packet( byte * buf, int length )
1484*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1485*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
1486*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int remainder;
1487*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int lines;
1488*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1489*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf("Packet of length %d \n", length );
1490*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1491*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #if SMC_DEBUG > 3
1492*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	lines = length / 16;
1493*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	remainder = length % 16;
1494*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1495*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for ( i = 0; i < lines ; i ++ ) {
1496*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		int cur;
1497*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1498*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		for ( cur = 0; cur < 8; cur ++ ) {
1499*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			byte a, b;
1500*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1501*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			a = *(buf ++ );
1502*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			b = *(buf ++ );
1503*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("%02x%02x ", a, b );
1504*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
1505*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("\n");
1506*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1507*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for ( i = 0; i < remainder/2 ; i++ ) {
1508*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		byte a, b;
1509*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1510*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		a = *(buf ++ );
1511*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		b = *(buf ++ );
1512*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("%02x%02x ", a, b );
1513*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1514*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf("\n");
1515*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
1516*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1517*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
1518*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1519*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_init(bd_t *bd) {
1520*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef SHARED_RESOURCES
1521*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	swap_to(ETHERNET);
1522*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
1523*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return (smc_open(bd));
1524*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1525*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1526*2439e4bfSJean-Christophe PLAGNIOL-VILLARD void eth_halt() {
1527*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_close();
1528*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1529*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1530*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_rx() {
1531*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return smc_rcv();
1532*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1533*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1534*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_send(volatile void *packet, int length) {
1535*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return smc_send_packet(packet, length);
1536*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1537*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1538*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int smc_get_ethaddr (bd_t * bd)
1539*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1540*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int env_size, rom_valid, env_present = 0, reg;
1541*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	char *s = NULL, *e, es[] = "11:22:33:44:55:66";
1542*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	char s_env_mac[64];
1543*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	uchar v_env_mac[6], v_rom_mac[6], *v_mac;
1544*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1545*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac));
1546*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if ((env_size > 0) && (env_size < sizeof (es))) {	/* exit if env is bad */
1547*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf ("\n*** ERROR: ethaddr is not set properly!!\n");
1548*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return (-1);
1549*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1550*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1551*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (env_size > 0) {
1552*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		env_present = 1;
1553*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		s = s_env_mac;
1554*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1555*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1556*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */
1557*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		v_env_mac[reg] = s ? simple_strtoul (s, &e, 16) : 0;
1558*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (s)
1559*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			s = (*e) ? e + 1 : e;
1560*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1561*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1562*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	rom_valid = get_rom_mac (v_rom_mac);	/* get ROM mac value if any */
1563*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1564*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (!env_present) {	/* if NO env */
1565*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (rom_valid) {	/* but ROM is valid */
1566*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			v_mac = v_rom_mac;
1567*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X",
1568*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 v_mac[0], v_mac[1], v_mac[2], v_mac[3],
1569*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				 v_mac[4], v_mac[5]);
1570*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			setenv ("ethaddr", s_env_mac);
1571*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		} else {	/* no env, bad ROM */
1572*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("\n*** ERROR: ethaddr is NOT set !!\n");
1573*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			return (-1);
1574*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
1575*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else {		/* good env, don't care ROM */
1576*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		v_mac = v_env_mac;	/* always use a good env over a ROM */
1577*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1578*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1579*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (env_present && rom_valid) { /* if both env and ROM are good */
1580*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (memcmp (v_env_mac, v_rom_mac, 6) != 0) {
1581*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("\nWarning: MAC addresses don't match:\n");
1582*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("\tHW MAC address:  "
1583*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				"%02X:%02X:%02X:%02X:%02X:%02X\n",
1584*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				v_rom_mac[0], v_rom_mac[1],
1585*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				v_rom_mac[2], v_rom_mac[3],
1586*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				v_rom_mac[4], v_rom_mac[5] );
1587*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf ("\t\"ethaddr\" value: "
1588*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				"%02X:%02X:%02X:%02X:%02X:%02X\n",
1589*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				v_env_mac[0], v_env_mac[1],
1590*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				v_env_mac[2], v_env_mac[3],
1591*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 				v_env_mac[4], v_env_mac[5]) ;
1592*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 			debug ("### Set MAC addr from environment\n");
1593*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
1594*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1595*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	memcpy (bd->bi_enetaddr, v_mac, 6);	/* update global address to match env (allows env changing) */
1596*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	smc_set_mac_addr ((uchar *)v_mac);	/* use old function to update smc default */
1597*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1],
1598*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		v_mac[2], v_mac[3], v_mac[4], v_mac[5]);
1599*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return (0);
1600*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1601*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1602*2439e4bfSJean-Christophe PLAGNIOL-VILLARD int get_rom_mac (uchar *v_rom_mac)
1603*2439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1604*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef HARDCODE_MAC	/* used for testing or to supress run time warnings */
1605*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 };
1606*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1607*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	memcpy (v_rom_mac, hw_mac_addr, 6);
1608*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return (1);
1609*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #else
1610*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i;
1611*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int valid_mac = 0;
1612*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1613*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	SMC_SELECT_BANK (1);
1614*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i=0; i<6; i++)
1615*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	{
1616*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		v_rom_mac[i] = SMC_inb ((ADDR0_REG + i));
1617*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 		valid_mac |= v_rom_mac[i];
1618*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
1619*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1620*2439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return (valid_mac ? 1 : 0);
1621*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif
1622*2439e4bfSJean-Christophe PLAGNIOL-VILLARD }
1623*2439e4bfSJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_DRIVER_SMC91111 */
1624