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