xref: /OK3568_Linux_fs/u-boot/drivers/net/ax88180.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * ax88180: ASIX AX88180 Non-PCI Gigabit Ethernet u-boot driver
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * This program is free software; you can distribute it and/or modify
5*4882a593Smuzhiyun  * it under the terms of the GNU General Public License (Version 2) as
6*4882a593Smuzhiyun  * published by the Free Software Foundation.
7*4882a593Smuzhiyun  * This program is distributed in the hope it will be useful, but
8*4882a593Smuzhiyun  * WITHOUT ANY WARRANTY; without even the implied warranty of
9*4882a593Smuzhiyun  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10*4882a593Smuzhiyun  * See the GNU General Public License for more details.
11*4882a593Smuzhiyun  * You should have received a copy of the GNU General Public License
12*4882a593Smuzhiyun  * along with this program; if not, write to the Free Software
13*4882a593Smuzhiyun  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
14*4882a593Smuzhiyun  * USA.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun /*
18*4882a593Smuzhiyun  * ========================================================================
19*4882a593Smuzhiyun  * ASIX AX88180 Non-PCI 16/32-bit Gigabit Ethernet Linux Driver
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * The AX88180 Ethernet controller is a high performance and highly
22*4882a593Smuzhiyun  * integrated local CPU bus Ethernet controller with embedded 40K bytes
23*4882a593Smuzhiyun  * SRAM and supports both 16-bit and 32-bit SRAM-Like interfaces for any
24*4882a593Smuzhiyun  * embedded systems.
25*4882a593Smuzhiyun  * The AX88180 is a single chip 10/100/1000Mbps Gigabit Ethernet
26*4882a593Smuzhiyun  * controller that supports both MII and RGMII interfaces and is
27*4882a593Smuzhiyun  * compliant to IEEE 802.3, IEEE 802.3u and IEEE 802.3z standards.
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * Please visit ASIX's web site (http://www.asix.com.tw) for more
30*4882a593Smuzhiyun  * details.
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  * Module Name	: ax88180.c
33*4882a593Smuzhiyun  * Date		: 2008-07-07
34*4882a593Smuzhiyun  * History
35*4882a593Smuzhiyun  * 09/06/2006	: New release for AX88180 US2 chip.
36*4882a593Smuzhiyun  * 07/07/2008	: Fix up the coding style and using inline functions
37*4882a593Smuzhiyun  *		  instead of macros
38*4882a593Smuzhiyun  * ========================================================================
39*4882a593Smuzhiyun  */
40*4882a593Smuzhiyun #include <common.h>
41*4882a593Smuzhiyun #include <command.h>
42*4882a593Smuzhiyun #include <net.h>
43*4882a593Smuzhiyun #include <malloc.h>
44*4882a593Smuzhiyun #include <linux/mii.h>
45*4882a593Smuzhiyun #include "ax88180.h"
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun  * ===========================================================================
49*4882a593Smuzhiyun  * Local SubProgram Declaration
50*4882a593Smuzhiyun  * ===========================================================================
51*4882a593Smuzhiyun  */
52*4882a593Smuzhiyun static void ax88180_rx_handler (struct eth_device *dev);
53*4882a593Smuzhiyun static int ax88180_phy_initial (struct eth_device *dev);
54*4882a593Smuzhiyun static void ax88180_media_config (struct eth_device *dev);
55*4882a593Smuzhiyun static unsigned long get_CicadaPHY_media_mode (struct eth_device *dev);
56*4882a593Smuzhiyun static unsigned long get_MarvellPHY_media_mode (struct eth_device *dev);
57*4882a593Smuzhiyun static unsigned short ax88180_mdio_read (struct eth_device *dev,
58*4882a593Smuzhiyun 					 unsigned long regaddr);
59*4882a593Smuzhiyun static void ax88180_mdio_write (struct eth_device *dev,
60*4882a593Smuzhiyun 				unsigned long regaddr, unsigned short regdata);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun /*
63*4882a593Smuzhiyun  * ===========================================================================
64*4882a593Smuzhiyun  * Local SubProgram Bodies
65*4882a593Smuzhiyun  * ===========================================================================
66*4882a593Smuzhiyun  */
ax88180_mdio_check_complete(struct eth_device * dev)67*4882a593Smuzhiyun static int ax88180_mdio_check_complete (struct eth_device *dev)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	int us_cnt = 10000;
70*4882a593Smuzhiyun 	unsigned short tmpval;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	/* MDIO read/write should not take more than 10 ms */
73*4882a593Smuzhiyun 	while (--us_cnt) {
74*4882a593Smuzhiyun 		tmpval = INW (dev, MDIOCTRL);
75*4882a593Smuzhiyun 		if (((tmpval & READ_PHY) == 0) && ((tmpval & WRITE_PHY) == 0))
76*4882a593Smuzhiyun 			break;
77*4882a593Smuzhiyun 	}
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	return us_cnt;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun static unsigned short
ax88180_mdio_read(struct eth_device * dev,unsigned long regaddr)83*4882a593Smuzhiyun ax88180_mdio_read (struct eth_device *dev, unsigned long regaddr)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
86*4882a593Smuzhiyun 	unsigned long tmpval = 0;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	OUTW (dev, (READ_PHY | (regaddr << 8) | priv->PhyAddr), MDIOCTRL);
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	if (ax88180_mdio_check_complete (dev))
91*4882a593Smuzhiyun 		tmpval = INW (dev, MDIODP);
92*4882a593Smuzhiyun 	else
93*4882a593Smuzhiyun 		printf ("Failed to read PHY register!\n");
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	return (unsigned short)(tmpval & 0xFFFF);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static void
ax88180_mdio_write(struct eth_device * dev,unsigned long regaddr,unsigned short regdata)99*4882a593Smuzhiyun ax88180_mdio_write (struct eth_device *dev, unsigned long regaddr,
100*4882a593Smuzhiyun 		    unsigned short regdata)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	OUTW (dev, regdata, MDIODP);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	OUTW (dev, (WRITE_PHY | (regaddr << 8) | priv->PhyAddr), MDIOCTRL);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	if (!ax88180_mdio_check_complete (dev))
109*4882a593Smuzhiyun 		printf ("Failed to write PHY register!\n");
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
ax88180_phy_reset(struct eth_device * dev)112*4882a593Smuzhiyun static int ax88180_phy_reset (struct eth_device *dev)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	unsigned short delay_cnt = 500;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	ax88180_mdio_write (dev, MII_BMCR, (BMCR_RESET | BMCR_ANENABLE));
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	/* Wait for the reset to complete, or time out (500 ms) */
119*4882a593Smuzhiyun 	while (ax88180_mdio_read (dev, MII_BMCR) & BMCR_RESET) {
120*4882a593Smuzhiyun 		udelay (1000);
121*4882a593Smuzhiyun 		if (--delay_cnt == 0) {
122*4882a593Smuzhiyun 			printf ("Failed to reset PHY!\n");
123*4882a593Smuzhiyun 			return -1;
124*4882a593Smuzhiyun 		}
125*4882a593Smuzhiyun 	}
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	return 0;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
ax88180_mac_reset(struct eth_device * dev)130*4882a593Smuzhiyun static void ax88180_mac_reset (struct eth_device *dev)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	unsigned long tmpval;
133*4882a593Smuzhiyun 	unsigned char i;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	struct {
136*4882a593Smuzhiyun 		unsigned short offset, value;
137*4882a593Smuzhiyun 	} program_seq[] = {
138*4882a593Smuzhiyun 		{
139*4882a593Smuzhiyun 		MISC, MISC_NORMAL}, {
140*4882a593Smuzhiyun 		RXINDICATOR, DEFAULT_RXINDICATOR}, {
141*4882a593Smuzhiyun 		TXCMD, DEFAULT_TXCMD}, {
142*4882a593Smuzhiyun 		TXBS, DEFAULT_TXBS}, {
143*4882a593Smuzhiyun 		TXDES0, DEFAULT_TXDES0}, {
144*4882a593Smuzhiyun 		TXDES1, DEFAULT_TXDES1}, {
145*4882a593Smuzhiyun 		TXDES2, DEFAULT_TXDES2}, {
146*4882a593Smuzhiyun 		TXDES3, DEFAULT_TXDES3}, {
147*4882a593Smuzhiyun 		TXCFG, DEFAULT_TXCFG}, {
148*4882a593Smuzhiyun 		MACCFG2, DEFAULT_MACCFG2}, {
149*4882a593Smuzhiyun 		MACCFG3, DEFAULT_MACCFG3}, {
150*4882a593Smuzhiyun 		TXLEN, DEFAULT_TXLEN}, {
151*4882a593Smuzhiyun 		RXBTHD0, DEFAULT_RXBTHD0}, {
152*4882a593Smuzhiyun 		RXBTHD1, DEFAULT_RXBTHD1}, {
153*4882a593Smuzhiyun 		RXFULTHD, DEFAULT_RXFULTHD}, {
154*4882a593Smuzhiyun 		DOGTHD0, DEFAULT_DOGTHD0}, {
155*4882a593Smuzhiyun 	DOGTHD1, DEFAULT_DOGTHD1},};
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	OUTW (dev, MISC_RESET_MAC, MISC);
158*4882a593Smuzhiyun 	tmpval = INW (dev, MISC);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(program_seq); i++)
161*4882a593Smuzhiyun 		OUTW (dev, program_seq[i].value, program_seq[i].offset);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
ax88180_poll_tx_complete(struct eth_device * dev)164*4882a593Smuzhiyun static int ax88180_poll_tx_complete (struct eth_device *dev)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
167*4882a593Smuzhiyun 	unsigned long tmpval, txbs_txdp;
168*4882a593Smuzhiyun 	int TimeOutCnt = 10000;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	txbs_txdp = 1 << priv->NextTxDesc;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	while (TimeOutCnt--) {
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 		tmpval = INW (dev, TXBS);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 		if ((tmpval & txbs_txdp) == 0)
177*4882a593Smuzhiyun 			break;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 		udelay (100);
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if (TimeOutCnt)
183*4882a593Smuzhiyun 		return 0;
184*4882a593Smuzhiyun 	else
185*4882a593Smuzhiyun 		return -TimeOutCnt;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
ax88180_rx_handler(struct eth_device * dev)188*4882a593Smuzhiyun static void ax88180_rx_handler (struct eth_device *dev)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
191*4882a593Smuzhiyun 	unsigned long data_size;
192*4882a593Smuzhiyun 	unsigned short rxcurt_ptr, rxbound_ptr, next_ptr;
193*4882a593Smuzhiyun 	int i;
194*4882a593Smuzhiyun #if defined (CONFIG_DRIVER_AX88180_16BIT)
195*4882a593Smuzhiyun 	unsigned short *rxdata = (unsigned short *)net_rx_packets[0];
196*4882a593Smuzhiyun #else
197*4882a593Smuzhiyun 	unsigned long *rxdata = (unsigned long *)net_rx_packets[0];
198*4882a593Smuzhiyun #endif
199*4882a593Smuzhiyun 	unsigned short count;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	rxcurt_ptr = INW (dev, RXCURT);
202*4882a593Smuzhiyun 	rxbound_ptr = INW (dev, RXBOUND);
203*4882a593Smuzhiyun 	next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	debug ("ax88180: RX original RXBOUND=0x%04x,"
206*4882a593Smuzhiyun 	       " RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	while (next_ptr != rxcurt_ptr) {
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		OUTW (dev, RX_START_READ, RXINDICATOR);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 		data_size = READ_RXBUF (dev) & 0xFFFF;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 		if ((data_size == 0) || (data_size > MAX_RX_SIZE)) {
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 			OUTW (dev, RX_STOP_READ, RXINDICATOR);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 			ax88180_mac_reset (dev);
219*4882a593Smuzhiyun 			printf ("ax88180: Invalid Rx packet length!"
220*4882a593Smuzhiyun 				" (len=0x%04lx)\n", data_size);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 			debug ("ax88180: RX RXBOUND=0x%04x,"
223*4882a593Smuzhiyun 			       "RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
224*4882a593Smuzhiyun 			return;
225*4882a593Smuzhiyun 		}
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 		rxbound_ptr += (((data_size + 0xF) & 0xFFF0) >> 4) + 1;
228*4882a593Smuzhiyun 		rxbound_ptr &= RX_PAGE_NUM_MASK;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 		/* Comput access times */
231*4882a593Smuzhiyun 		count = (data_size + priv->PadSize) >> priv->BusWidth;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 		for (i = 0; i < count; i++) {
234*4882a593Smuzhiyun 			*(rxdata + i) = READ_RXBUF (dev);
235*4882a593Smuzhiyun 		}
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 		OUTW (dev, RX_STOP_READ, RXINDICATOR);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 		/* Pass the packet up to the protocol layers. */
240*4882a593Smuzhiyun 		net_process_received_packet(net_rx_packets[0], data_size);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 		OUTW (dev, rxbound_ptr, RXBOUND);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 		rxcurt_ptr = INW (dev, RXCURT);
245*4882a593Smuzhiyun 		rxbound_ptr = INW (dev, RXBOUND);
246*4882a593Smuzhiyun 		next_ptr = (rxbound_ptr + 1) & RX_PAGE_NUM_MASK;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 		debug ("ax88180: RX updated RXBOUND=0x%04x,"
249*4882a593Smuzhiyun 		       "RXCURT=0x%04x\n", rxbound_ptr, rxcurt_ptr);
250*4882a593Smuzhiyun 	}
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	return;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
ax88180_phy_initial(struct eth_device * dev)255*4882a593Smuzhiyun static int ax88180_phy_initial (struct eth_device *dev)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
258*4882a593Smuzhiyun 	unsigned long tmp_regval;
259*4882a593Smuzhiyun 	unsigned short phyaddr;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	/* Search for first avaliable PHY chipset */
262*4882a593Smuzhiyun #ifdef CONFIG_PHY_ADDR
263*4882a593Smuzhiyun 	phyaddr = CONFIG_PHY_ADDR;
264*4882a593Smuzhiyun #else
265*4882a593Smuzhiyun 	for (phyaddr = 0; phyaddr < 32; ++phyaddr)
266*4882a593Smuzhiyun #endif
267*4882a593Smuzhiyun 	{
268*4882a593Smuzhiyun 		priv->PhyAddr = phyaddr;
269*4882a593Smuzhiyun 		priv->PhyID0 = ax88180_mdio_read(dev, MII_PHYSID1);
270*4882a593Smuzhiyun 		priv->PhyID1 = ax88180_mdio_read(dev, MII_PHYSID2);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 		switch (priv->PhyID0) {
273*4882a593Smuzhiyun 		case MARVELL_ALASKA_PHYSID0:
274*4882a593Smuzhiyun 			debug("ax88180: Found Marvell Alaska PHY family."
275*4882a593Smuzhiyun 			      " (PHY Addr=0x%x)\n", priv->PhyAddr);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 			switch (priv->PhyID1) {
278*4882a593Smuzhiyun 			case MARVELL_88E1118_PHYSID1:
279*4882a593Smuzhiyun 				ax88180_mdio_write(dev, M88E1118_PAGE_SEL, 2);
280*4882a593Smuzhiyun 				ax88180_mdio_write(dev, M88E1118_CR,
281*4882a593Smuzhiyun 					M88E1118_CR_DEFAULT);
282*4882a593Smuzhiyun 				ax88180_mdio_write(dev, M88E1118_PAGE_SEL, 3);
283*4882a593Smuzhiyun 				ax88180_mdio_write(dev, M88E1118_LEDCTL,
284*4882a593Smuzhiyun 					M88E1118_LEDCTL_DEFAULT);
285*4882a593Smuzhiyun 				ax88180_mdio_write(dev, M88E1118_LEDMIX,
286*4882a593Smuzhiyun 					M88E1118_LEDMIX_LED050 | M88E1118_LEDMIX_LED150 | 0x15);
287*4882a593Smuzhiyun 				ax88180_mdio_write(dev, M88E1118_PAGE_SEL, 0);
288*4882a593Smuzhiyun 			default: /* Default to 88E1111 Phy */
289*4882a593Smuzhiyun 				tmp_regval = ax88180_mdio_read(dev, M88E1111_EXT_SSR);
290*4882a593Smuzhiyun 				if ((tmp_regval & HWCFG_MODE_MASK) != RGMII_COPPER_MODE)
291*4882a593Smuzhiyun 					ax88180_mdio_write(dev, M88E1111_EXT_SCR,
292*4882a593Smuzhiyun 						DEFAULT_EXT_SCR);
293*4882a593Smuzhiyun 			}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 			if (ax88180_phy_reset(dev) < 0)
296*4882a593Smuzhiyun 				return 0;
297*4882a593Smuzhiyun 			ax88180_mdio_write(dev, M88_IER, LINK_CHANGE_INT);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 			return 1;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 		case CICADA_CIS8201_PHYSID0:
302*4882a593Smuzhiyun 			debug("ax88180: Found CICADA CIS8201 PHY"
303*4882a593Smuzhiyun 			      " chipset. (PHY Addr=0x%x)\n", priv->PhyAddr);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 			ax88180_mdio_write(dev, CIS_IMR,
306*4882a593Smuzhiyun 					    (CIS_INT_ENABLE | LINK_CHANGE_INT));
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 			/* Set CIS_SMI_PRIORITY bit before force the media mode */
309*4882a593Smuzhiyun 			tmp_regval = ax88180_mdio_read(dev, CIS_AUX_CTRL_STATUS);
310*4882a593Smuzhiyun 			tmp_regval &= ~CIS_SMI_PRIORITY;
311*4882a593Smuzhiyun 			ax88180_mdio_write(dev, CIS_AUX_CTRL_STATUS, tmp_regval);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 			return 1;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 		case 0xffff:
316*4882a593Smuzhiyun 			/* No PHY at this addr */
317*4882a593Smuzhiyun 			break;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 		default:
320*4882a593Smuzhiyun 			printf("ax88180: Unknown PHY chipset %#x at addr %#x\n",
321*4882a593Smuzhiyun 			       priv->PhyID0, priv->PhyAddr);
322*4882a593Smuzhiyun 			break;
323*4882a593Smuzhiyun 		}
324*4882a593Smuzhiyun 	}
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	printf("ax88180: Unknown PHY chipset!!\n");
327*4882a593Smuzhiyun 	return 0;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
ax88180_media_config(struct eth_device * dev)330*4882a593Smuzhiyun static void ax88180_media_config (struct eth_device *dev)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
333*4882a593Smuzhiyun 	unsigned long bmcr_val, bmsr_val;
334*4882a593Smuzhiyun 	unsigned long rxcfg_val, maccfg0_val, maccfg1_val;
335*4882a593Smuzhiyun 	unsigned long RealMediaMode;
336*4882a593Smuzhiyun 	int i;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	/* Waiting 2 seconds for PHY link stable */
339*4882a593Smuzhiyun 	for (i = 0; i < 20000; i++) {
340*4882a593Smuzhiyun 		bmsr_val = ax88180_mdio_read (dev, MII_BMSR);
341*4882a593Smuzhiyun 		if (bmsr_val & BMSR_LSTATUS) {
342*4882a593Smuzhiyun 			break;
343*4882a593Smuzhiyun 		}
344*4882a593Smuzhiyun 		udelay (100);
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	bmsr_val = ax88180_mdio_read (dev, MII_BMSR);
348*4882a593Smuzhiyun 	debug ("ax88180: BMSR=0x%04x\n", (unsigned int)bmsr_val);
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	if (bmsr_val & BMSR_LSTATUS) {
351*4882a593Smuzhiyun 		bmcr_val = ax88180_mdio_read (dev, MII_BMCR);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 		if (bmcr_val & BMCR_ANENABLE) {
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 			/*
356*4882a593Smuzhiyun 			 * Waiting for Auto-negotiation completion, this may
357*4882a593Smuzhiyun 			 * take up to 5 seconds.
358*4882a593Smuzhiyun 			 */
359*4882a593Smuzhiyun 			debug ("ax88180: Auto-negotiation is "
360*4882a593Smuzhiyun 			       "enabled. Waiting for NWay completion..\n");
361*4882a593Smuzhiyun 			for (i = 0; i < 50000; i++) {
362*4882a593Smuzhiyun 				bmsr_val = ax88180_mdio_read (dev, MII_BMSR);
363*4882a593Smuzhiyun 				if (bmsr_val & BMSR_ANEGCOMPLETE) {
364*4882a593Smuzhiyun 					break;
365*4882a593Smuzhiyun 				}
366*4882a593Smuzhiyun 				udelay (100);
367*4882a593Smuzhiyun 			}
368*4882a593Smuzhiyun 		} else
369*4882a593Smuzhiyun 			debug ("ax88180: Auto-negotiation is disabled.\n");
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 		debug ("ax88180: BMCR=0x%04x, BMSR=0x%04x\n",
372*4882a593Smuzhiyun 		       (unsigned int)bmcr_val, (unsigned int)bmsr_val);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 		/* Get real media mode here */
375*4882a593Smuzhiyun 		switch (priv->PhyID0) {
376*4882a593Smuzhiyun 		case MARVELL_ALASKA_PHYSID0:
377*4882a593Smuzhiyun 			RealMediaMode = get_MarvellPHY_media_mode(dev);
378*4882a593Smuzhiyun 			break;
379*4882a593Smuzhiyun 		case CICADA_CIS8201_PHYSID0:
380*4882a593Smuzhiyun 			RealMediaMode = get_CicadaPHY_media_mode(dev);
381*4882a593Smuzhiyun 			break;
382*4882a593Smuzhiyun 		default:
383*4882a593Smuzhiyun 			RealMediaMode = MEDIA_1000FULL;
384*4882a593Smuzhiyun 			break;
385*4882a593Smuzhiyun 		}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 		priv->LinkState = INS_LINK_UP;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 		switch (RealMediaMode) {
390*4882a593Smuzhiyun 		case MEDIA_1000FULL:
391*4882a593Smuzhiyun 			debug ("ax88180: 1000Mbps Full-duplex mode.\n");
392*4882a593Smuzhiyun 			rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
393*4882a593Smuzhiyun 			maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0;
394*4882a593Smuzhiyun 			maccfg1_val = GIGA_MODE_EN | RXFLOW_EN |
395*4882a593Smuzhiyun 			    FULLDUPLEX | DEFAULT_MACCFG1;
396*4882a593Smuzhiyun 			break;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 		case MEDIA_1000HALF:
399*4882a593Smuzhiyun 			debug ("ax88180: 1000Mbps Half-duplex mode.\n");
400*4882a593Smuzhiyun 			rxcfg_val = DEFAULT_RXCFG;
401*4882a593Smuzhiyun 			maccfg0_val = DEFAULT_MACCFG0;
402*4882a593Smuzhiyun 			maccfg1_val = GIGA_MODE_EN | DEFAULT_MACCFG1;
403*4882a593Smuzhiyun 			break;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 		case MEDIA_100FULL:
406*4882a593Smuzhiyun 			debug ("ax88180: 100Mbps Full-duplex mode.\n");
407*4882a593Smuzhiyun 			rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
408*4882a593Smuzhiyun 			maccfg0_val = SPEED100 | TXFLOW_ENABLE
409*4882a593Smuzhiyun 			    | DEFAULT_MACCFG0;
410*4882a593Smuzhiyun 			maccfg1_val = RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1;
411*4882a593Smuzhiyun 			break;
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 		case MEDIA_100HALF:
414*4882a593Smuzhiyun 			debug ("ax88180: 100Mbps Half-duplex mode.\n");
415*4882a593Smuzhiyun 			rxcfg_val = DEFAULT_RXCFG;
416*4882a593Smuzhiyun 			maccfg0_val = SPEED100 | DEFAULT_MACCFG0;
417*4882a593Smuzhiyun 			maccfg1_val = DEFAULT_MACCFG1;
418*4882a593Smuzhiyun 			break;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 		case MEDIA_10FULL:
421*4882a593Smuzhiyun 			debug ("ax88180: 10Mbps Full-duplex mode.\n");
422*4882a593Smuzhiyun 			rxcfg_val = RXFLOW_ENABLE | DEFAULT_RXCFG;
423*4882a593Smuzhiyun 			maccfg0_val = TXFLOW_ENABLE | DEFAULT_MACCFG0;
424*4882a593Smuzhiyun 			maccfg1_val = RXFLOW_EN | FULLDUPLEX | DEFAULT_MACCFG1;
425*4882a593Smuzhiyun 			break;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 		case MEDIA_10HALF:
428*4882a593Smuzhiyun 			debug ("ax88180: 10Mbps Half-duplex mode.\n");
429*4882a593Smuzhiyun 			rxcfg_val = DEFAULT_RXCFG;
430*4882a593Smuzhiyun 			maccfg0_val = DEFAULT_MACCFG0;
431*4882a593Smuzhiyun 			maccfg1_val = DEFAULT_MACCFG1;
432*4882a593Smuzhiyun 			break;
433*4882a593Smuzhiyun 		default:
434*4882a593Smuzhiyun 			debug ("ax88180: Unknow media mode.\n");
435*4882a593Smuzhiyun 			rxcfg_val = DEFAULT_RXCFG;
436*4882a593Smuzhiyun 			maccfg0_val = DEFAULT_MACCFG0;
437*4882a593Smuzhiyun 			maccfg1_val = DEFAULT_MACCFG1;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 			priv->LinkState = INS_LINK_DOWN;
440*4882a593Smuzhiyun 			break;
441*4882a593Smuzhiyun 		}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	} else {
444*4882a593Smuzhiyun 		rxcfg_val = DEFAULT_RXCFG;
445*4882a593Smuzhiyun 		maccfg0_val = DEFAULT_MACCFG0;
446*4882a593Smuzhiyun 		maccfg1_val = DEFAULT_MACCFG1;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 		priv->LinkState = INS_LINK_DOWN;
449*4882a593Smuzhiyun 	}
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	OUTW (dev, rxcfg_val, RXCFG);
452*4882a593Smuzhiyun 	OUTW (dev, maccfg0_val, MACCFG0);
453*4882a593Smuzhiyun 	OUTW (dev, maccfg1_val, MACCFG1);
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	return;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
get_MarvellPHY_media_mode(struct eth_device * dev)458*4882a593Smuzhiyun static unsigned long get_MarvellPHY_media_mode (struct eth_device *dev)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun 	unsigned long m88_ssr;
461*4882a593Smuzhiyun 	unsigned long MediaMode;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	m88_ssr = ax88180_mdio_read (dev, M88_SSR);
464*4882a593Smuzhiyun 	switch (m88_ssr & SSR_MEDIA_MASK) {
465*4882a593Smuzhiyun 	case SSR_1000FULL:
466*4882a593Smuzhiyun 		MediaMode = MEDIA_1000FULL;
467*4882a593Smuzhiyun 		break;
468*4882a593Smuzhiyun 	case SSR_1000HALF:
469*4882a593Smuzhiyun 		MediaMode = MEDIA_1000HALF;
470*4882a593Smuzhiyun 		break;
471*4882a593Smuzhiyun 	case SSR_100FULL:
472*4882a593Smuzhiyun 		MediaMode = MEDIA_100FULL;
473*4882a593Smuzhiyun 		break;
474*4882a593Smuzhiyun 	case SSR_100HALF:
475*4882a593Smuzhiyun 		MediaMode = MEDIA_100HALF;
476*4882a593Smuzhiyun 		break;
477*4882a593Smuzhiyun 	case SSR_10FULL:
478*4882a593Smuzhiyun 		MediaMode = MEDIA_10FULL;
479*4882a593Smuzhiyun 		break;
480*4882a593Smuzhiyun 	case SSR_10HALF:
481*4882a593Smuzhiyun 		MediaMode = MEDIA_10HALF;
482*4882a593Smuzhiyun 		break;
483*4882a593Smuzhiyun 	default:
484*4882a593Smuzhiyun 		MediaMode = MEDIA_UNKNOWN;
485*4882a593Smuzhiyun 		break;
486*4882a593Smuzhiyun 	}
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	return MediaMode;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun 
get_CicadaPHY_media_mode(struct eth_device * dev)491*4882a593Smuzhiyun static unsigned long get_CicadaPHY_media_mode (struct eth_device *dev)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun 	unsigned long tmp_regval;
494*4882a593Smuzhiyun 	unsigned long MediaMode;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	tmp_regval = ax88180_mdio_read (dev, CIS_AUX_CTRL_STATUS);
497*4882a593Smuzhiyun 	switch (tmp_regval & CIS_MEDIA_MASK) {
498*4882a593Smuzhiyun 	case CIS_1000FULL:
499*4882a593Smuzhiyun 		MediaMode = MEDIA_1000FULL;
500*4882a593Smuzhiyun 		break;
501*4882a593Smuzhiyun 	case CIS_1000HALF:
502*4882a593Smuzhiyun 		MediaMode = MEDIA_1000HALF;
503*4882a593Smuzhiyun 		break;
504*4882a593Smuzhiyun 	case CIS_100FULL:
505*4882a593Smuzhiyun 		MediaMode = MEDIA_100FULL;
506*4882a593Smuzhiyun 		break;
507*4882a593Smuzhiyun 	case CIS_100HALF:
508*4882a593Smuzhiyun 		MediaMode = MEDIA_100HALF;
509*4882a593Smuzhiyun 		break;
510*4882a593Smuzhiyun 	case CIS_10FULL:
511*4882a593Smuzhiyun 		MediaMode = MEDIA_10FULL;
512*4882a593Smuzhiyun 		break;
513*4882a593Smuzhiyun 	case CIS_10HALF:
514*4882a593Smuzhiyun 		MediaMode = MEDIA_10HALF;
515*4882a593Smuzhiyun 		break;
516*4882a593Smuzhiyun 	default:
517*4882a593Smuzhiyun 		MediaMode = MEDIA_UNKNOWN;
518*4882a593Smuzhiyun 		break;
519*4882a593Smuzhiyun 	}
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	return MediaMode;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun 
ax88180_halt(struct eth_device * dev)524*4882a593Smuzhiyun static void ax88180_halt (struct eth_device *dev)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun 	/* Disable AX88180 TX/RX functions */
527*4882a593Smuzhiyun 	OUTW (dev, WAKEMOD, CMD);
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun 
ax88180_init(struct eth_device * dev,bd_t * bd)530*4882a593Smuzhiyun static int ax88180_init (struct eth_device *dev, bd_t * bd)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun 	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
533*4882a593Smuzhiyun 	unsigned short tmp_regval;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	ax88180_mac_reset (dev);
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	/* Disable interrupt */
538*4882a593Smuzhiyun 	OUTW (dev, CLEAR_IMR, IMR);
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	/* Disable AX88180 TX/RX functions */
541*4882a593Smuzhiyun 	OUTW (dev, WAKEMOD, CMD);
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	/* Fill the MAC address */
544*4882a593Smuzhiyun 	tmp_regval =
545*4882a593Smuzhiyun 	    dev->enetaddr[0] | (((unsigned short)dev->enetaddr[1]) << 8);
546*4882a593Smuzhiyun 	OUTW (dev, tmp_regval, MACID0);
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	tmp_regval =
549*4882a593Smuzhiyun 	    dev->enetaddr[2] | (((unsigned short)dev->enetaddr[3]) << 8);
550*4882a593Smuzhiyun 	OUTW (dev, tmp_regval, MACID1);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	tmp_regval =
553*4882a593Smuzhiyun 	    dev->enetaddr[4] | (((unsigned short)dev->enetaddr[5]) << 8);
554*4882a593Smuzhiyun 	OUTW (dev, tmp_regval, MACID2);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	ax88180_media_config (dev);
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	OUTW (dev, DEFAULT_RXFILTER, RXFILTER);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	/* Initial variables here */
561*4882a593Smuzhiyun 	priv->FirstTxDesc = TXDP0;
562*4882a593Smuzhiyun 	priv->NextTxDesc = TXDP0;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	/* Check if there is any invalid interrupt status and clear it. */
565*4882a593Smuzhiyun 	OUTW (dev, INW (dev, ISR), ISR);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	/* Start AX88180 TX/RX functions */
568*4882a593Smuzhiyun 	OUTW (dev, (RXEN | TXEN | WAKEMOD), CMD);
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	return 0;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun /* Get a data block via Ethernet */
ax88180_recv(struct eth_device * dev)574*4882a593Smuzhiyun static int ax88180_recv (struct eth_device *dev)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun 	unsigned short ISR_Status;
577*4882a593Smuzhiyun 	unsigned short tmp_regval;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	/* Read and check interrupt status here. */
580*4882a593Smuzhiyun 	ISR_Status = INW (dev, ISR);
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	while (ISR_Status) {
583*4882a593Smuzhiyun 		/* Clear the interrupt status */
584*4882a593Smuzhiyun 		OUTW (dev, ISR_Status, ISR);
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 		debug ("\nax88180: The interrupt status = 0x%04x\n",
587*4882a593Smuzhiyun 		       ISR_Status);
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 		if (ISR_Status & ISR_PHY) {
590*4882a593Smuzhiyun 			/* Read ISR register once to clear PHY interrupt bit */
591*4882a593Smuzhiyun 			tmp_regval = ax88180_mdio_read (dev, M88_ISR);
592*4882a593Smuzhiyun 			ax88180_media_config (dev);
593*4882a593Smuzhiyun 		}
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 		if ((ISR_Status & ISR_RX) || (ISR_Status & ISR_RXBUFFOVR)) {
596*4882a593Smuzhiyun 			ax88180_rx_handler (dev);
597*4882a593Smuzhiyun 		}
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 		/* Read and check interrupt status again */
600*4882a593Smuzhiyun 		ISR_Status = INW (dev, ISR);
601*4882a593Smuzhiyun 	}
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	return 0;
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun /* Send a data block via Ethernet. */
ax88180_send(struct eth_device * dev,void * packet,int length)607*4882a593Smuzhiyun static int ax88180_send(struct eth_device *dev, void *packet, int length)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun 	struct ax88180_private *priv = (struct ax88180_private *)dev->priv;
610*4882a593Smuzhiyun 	unsigned short TXDES_addr;
611*4882a593Smuzhiyun 	unsigned short txcmd_txdp, txbs_txdp;
612*4882a593Smuzhiyun 	unsigned short tmp_data;
613*4882a593Smuzhiyun 	int i;
614*4882a593Smuzhiyun #if defined (CONFIG_DRIVER_AX88180_16BIT)
615*4882a593Smuzhiyun 	volatile unsigned short *txdata = (volatile unsigned short *)packet;
616*4882a593Smuzhiyun #else
617*4882a593Smuzhiyun 	volatile unsigned long *txdata = (volatile unsigned long *)packet;
618*4882a593Smuzhiyun #endif
619*4882a593Smuzhiyun 	unsigned short count;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	if (priv->LinkState != INS_LINK_UP) {
622*4882a593Smuzhiyun 		return 0;
623*4882a593Smuzhiyun 	}
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	priv->FirstTxDesc = priv->NextTxDesc;
626*4882a593Smuzhiyun 	txbs_txdp = 1 << priv->FirstTxDesc;
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	debug ("ax88180: TXDP%d is available\n", priv->FirstTxDesc);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	txcmd_txdp = priv->FirstTxDesc << 13;
631*4882a593Smuzhiyun 	TXDES_addr = TXDES0 + (priv->FirstTxDesc << 2);
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	OUTW (dev, (txcmd_txdp | length | TX_START_WRITE), TXCMD);
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	/* Comput access times */
636*4882a593Smuzhiyun 	count = (length + priv->PadSize) >> priv->BusWidth;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
639*4882a593Smuzhiyun 		WRITE_TXBUF (dev, *(txdata + i));
640*4882a593Smuzhiyun 	}
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	OUTW (dev, txcmd_txdp | length, TXCMD);
643*4882a593Smuzhiyun 	OUTW (dev, txbs_txdp, TXBS);
644*4882a593Smuzhiyun 	OUTW (dev, (TXDPx_ENABLE | length), TXDES_addr);
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	priv->NextTxDesc = (priv->NextTxDesc + 1) & TXDP_MASK;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	/*
649*4882a593Smuzhiyun 	 * Check the available transmit descriptor, if we had exhausted all
650*4882a593Smuzhiyun 	 * transmit descriptor ,then we have to wait for at least one free
651*4882a593Smuzhiyun 	 * descriptor
652*4882a593Smuzhiyun 	 */
653*4882a593Smuzhiyun 	txbs_txdp = 1 << priv->NextTxDesc;
654*4882a593Smuzhiyun 	tmp_data = INW (dev, TXBS);
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 	if (tmp_data & txbs_txdp) {
657*4882a593Smuzhiyun 		if (ax88180_poll_tx_complete (dev) < 0) {
658*4882a593Smuzhiyun 			ax88180_mac_reset (dev);
659*4882a593Smuzhiyun 			priv->FirstTxDesc = TXDP0;
660*4882a593Smuzhiyun 			priv->NextTxDesc = TXDP0;
661*4882a593Smuzhiyun 			printf ("ax88180: Transmit time out occurred!\n");
662*4882a593Smuzhiyun 		}
663*4882a593Smuzhiyun 	}
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	return 0;
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun 
ax88180_read_mac_addr(struct eth_device * dev)668*4882a593Smuzhiyun static void ax88180_read_mac_addr (struct eth_device *dev)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun 	unsigned short macid0_val, macid1_val, macid2_val;
671*4882a593Smuzhiyun 	unsigned short tmp_regval;
672*4882a593Smuzhiyun 	unsigned short i;
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	/* Reload MAC address from EEPROM */
675*4882a593Smuzhiyun 	OUTW (dev, RELOAD_EEPROM, PROMCTRL);
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	/* Waiting for reload eeprom completion */
678*4882a593Smuzhiyun 	for (i = 0; i < 500; i++) {
679*4882a593Smuzhiyun 		tmp_regval = INW (dev, PROMCTRL);
680*4882a593Smuzhiyun 		if ((tmp_regval & RELOAD_EEPROM) == 0)
681*4882a593Smuzhiyun 			break;
682*4882a593Smuzhiyun 		udelay (1000);
683*4882a593Smuzhiyun 	}
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	/* Get MAC addresses */
686*4882a593Smuzhiyun 	macid0_val = INW (dev, MACID0);
687*4882a593Smuzhiyun 	macid1_val = INW (dev, MACID1);
688*4882a593Smuzhiyun 	macid2_val = INW (dev, MACID2);
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun 	if (((macid0_val | macid1_val | macid2_val) != 0) &&
691*4882a593Smuzhiyun 	    ((macid0_val & 0x01) == 0)) {
692*4882a593Smuzhiyun 		dev->enetaddr[0] = (unsigned char)macid0_val;
693*4882a593Smuzhiyun 		dev->enetaddr[1] = (unsigned char)(macid0_val >> 8);
694*4882a593Smuzhiyun 		dev->enetaddr[2] = (unsigned char)macid1_val;
695*4882a593Smuzhiyun 		dev->enetaddr[3] = (unsigned char)(macid1_val >> 8);
696*4882a593Smuzhiyun 		dev->enetaddr[4] = (unsigned char)macid2_val;
697*4882a593Smuzhiyun 		dev->enetaddr[5] = (unsigned char)(macid2_val >> 8);
698*4882a593Smuzhiyun 	}
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun /* Exported SubProgram Bodies */
ax88180_initialize(bd_t * bis)702*4882a593Smuzhiyun int ax88180_initialize (bd_t * bis)
703*4882a593Smuzhiyun {
704*4882a593Smuzhiyun 	struct eth_device *dev;
705*4882a593Smuzhiyun 	struct ax88180_private *priv;
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	dev = (struct eth_device *)malloc (sizeof *dev);
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	if (NULL == dev)
710*4882a593Smuzhiyun 		return 0;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	memset (dev, 0, sizeof *dev);
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	priv = (struct ax88180_private *)malloc (sizeof (*priv));
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	if (NULL == priv)
717*4882a593Smuzhiyun 		return 0;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	memset (priv, 0, sizeof *priv);
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	strcpy(dev->name, "ax88180");
722*4882a593Smuzhiyun 	dev->iobase = AX88180_BASE;
723*4882a593Smuzhiyun 	dev->priv = priv;
724*4882a593Smuzhiyun 	dev->init = ax88180_init;
725*4882a593Smuzhiyun 	dev->halt = ax88180_halt;
726*4882a593Smuzhiyun 	dev->send = ax88180_send;
727*4882a593Smuzhiyun 	dev->recv = ax88180_recv;
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	priv->BusWidth = BUS_WIDTH_32;
730*4882a593Smuzhiyun 	priv->PadSize = 3;
731*4882a593Smuzhiyun #if defined (CONFIG_DRIVER_AX88180_16BIT)
732*4882a593Smuzhiyun 	OUTW (dev, (START_BASE >> 8), BASE);
733*4882a593Smuzhiyun 	OUTW (dev, DECODE_EN, DECODE);
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	priv->BusWidth = BUS_WIDTH_16;
736*4882a593Smuzhiyun 	priv->PadSize = 1;
737*4882a593Smuzhiyun #endif
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	ax88180_mac_reset (dev);
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	/* Disable interrupt */
742*4882a593Smuzhiyun 	OUTW (dev, CLEAR_IMR, IMR);
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	/* Disable AX88180 TX/RX functions */
745*4882a593Smuzhiyun 	OUTW (dev, WAKEMOD, CMD);
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	ax88180_read_mac_addr (dev);
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	eth_register (dev);
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	return ax88180_phy_initial (dev);
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun }
754