blob: 08248f440720f99a758ba6a58dcafd99e87a75b0 [file] [log] [blame]
wdenk7ac16102004-08-01 22:48:16 +00001/*
2 dm9000.c: Version 1.2 12/15/2003
3
4 A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
5 Copyright (C) 1997 Sten Wang
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
18
19V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match
Wolfgang Denka1be4762008-05-20 16:00:29 +020020 06/22/2001 Support DM9801 progrmming
21 E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
22 E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
23 R17 = (R17 & 0xfff0) | NF + 3
24 E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
25 R17 = (R17 & 0xfff0) | NF
wdenk7ac16102004-08-01 22:48:16 +000026
Wolfgang Denka1be4762008-05-20 16:00:29 +020027v1.00 modify by simon 2001.9.5
wdenk7ac16102004-08-01 22:48:16 +000028 change for kernel 2.4.x
29
Wolfgang Denka1be4762008-05-20 16:00:29 +020030v1.1 11/09/2001 fix force mode bug
wdenk7ac16102004-08-01 22:48:16 +000031
32v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>:
33 Fixed phy reset.
34 Added tx/rx 32 bit mode.
35 Cleaned up for kernel merge.
36
37--------------------------------------
38
Remy Bohmer5f63bf42008-06-03 15:26:21 +020039 12/15/2003 Initial port to u-boot by
40 Sascha Hauer <saschahauer@web.de>
41
42 06/03/2008 Remy Bohmer <linux@bohmer.net>
Remy Bohmereec38a12008-06-03 15:26:25 +020043 - Fixed the driver to work with DM9000A.
44 (check on ISR receive status bit before reading the
45 FIFO as described in DM9000 programming guide and
46 application notes)
Remy Bohmer5f63bf42008-06-03 15:26:21 +020047 - Added autodetect of databus width.
Remy Bohmerf4329dc2008-06-03 15:26:22 +020048 - Made debug code compile again.
Remy Bohmer16cb2642008-06-03 15:26:23 +020049 - Adapt eth_send such that it matches the DM9000*
50 application notes. Needed to make it work properly
51 for DM9000A.
Remy Bohmer2f13d2c2008-06-03 15:26:24 +020052 - Adapted reset procedure to match DM9000 application
53 notes (i.e. double reset)
Remy Bohmer5f63bf42008-06-03 15:26:21 +020054 These changes are tested with DM9000{A,EP,E} together
55 with a 200MHz Atmel AT91SAM92161 core
wdenk7ac16102004-08-01 22:48:16 +000056
57TODO: Homerun NIC and longrun NIC are not functional, only internal at the
58 moment.
59*/
60
61#include <common.h>
62#include <command.h>
63#include <net.h>
64#include <asm/io.h>
65
66#ifdef CONFIG_DRIVER_DM9000
67
68#include "dm9000x.h"
69
70/* Board/System/Debug information/definition ---------------- */
71
72#define DM9801_NOISE_FLOOR 0x08
73#define DM9802_NOISE_FLOOR 0x05
74
75/* #define CONFIG_DM9000_DEBUG */
76
77#ifdef CONFIG_DM9000_DEBUG
Remy Bohmerf4329dc2008-06-03 15:26:22 +020078#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
79#define DM9000_DMP_PACKET(func,packet,length) \
80 do { \
81 int i; \
82 printf(func ": length: %d\n", length); \
83 for (i = 0; i < length; i++) { \
84 if (i % 8 == 0) \
85 printf("\n%s: %02x: ", func, i); \
86 printf("%02x ", ((unsigned char *) packet)[i]); \
87 } printf("\n"); \
88 } while(0)
89#else
wdenk7ac16102004-08-01 22:48:16 +000090#define DM9000_DBG(fmt,args...)
Remy Bohmerf4329dc2008-06-03 15:26:22 +020091#define DM9000_DMP_PACKET(func,packet,length)
92#endif
93
wdenk7ac16102004-08-01 22:48:16 +000094enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD =
95 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO =
96 8, DM9000_1M_HPNA = 0x10
97};
98enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2
99};
100
101/* Structure/enum declaration ------------------------------- */
102typedef struct board_info {
103 u32 runt_length_counter; /* counter: RX length < 64byte */
104 u32 long_length_counter; /* counter: RX length > 1514byte */
105 u32 reset_counter; /* counter: RESET */
106 u32 reset_tx_timeout; /* RESET caused by TX Timeout */
107 u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
108 u16 tx_pkt_cnt;
109 u16 queue_start_addr;
110 u16 dbug_cnt;
111 u8 phy_addr;
112 u8 device_wait_reset; /* device state */
113 u8 nic_type; /* NIC type */
114 unsigned char srom[128];
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200115 void (*outblk)(void *data_ptr, int count);
116 void (*inblk)(void *data_ptr, int count);
117 void (*rx_status)(u16 *RxStatus, u16 *RxLen);
118 } board_info_t;
119static board_info_t dm9000_info;
wdenk7ac16102004-08-01 22:48:16 +0000120
121/* For module input parameter */
122static int media_mode = DM9000_AUTO;
123static u8 nfloor = 0;
124
125/* function declaration ------------------------------------- */
126int eth_init(bd_t * bd);
127int eth_send(volatile void *, int);
128int eth_rx(void);
129void eth_halt(void);
130static int dm9000_probe(void);
131static u16 phy_read(int);
132static void phy_write(int, u16);
stefano babic6708a602007-08-30 23:01:49 +0200133u16 read_srom_word(int);
wdenk7ac16102004-08-01 22:48:16 +0000134static u8 DM9000_ior(int);
135static void DM9000_iow(int reg, u8 value);
136
137/* DM9000 network board routine ---------------------------- */
138
139#define DM9000_outb(d,r) ( *(volatile u8 *)r = d )
140#define DM9000_outw(d,r) ( *(volatile u16 *)r = d )
141#define DM9000_outl(d,r) ( *(volatile u32 *)r = d )
142#define DM9000_inb(r) (*(volatile u8 *)r)
143#define DM9000_inw(r) (*(volatile u16 *)r)
144#define DM9000_inl(r) (*(volatile u32 *)r)
145
146#ifdef CONFIG_DM9000_DEBUG
147static void
148dump_regs(void)
149{
150 DM9000_DBG("\n");
151 DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0));
152 DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1));
153 DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2));
154 DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3));
155 DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
156 DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
157 DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200158 DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
wdenk7ac16102004-08-01 22:48:16 +0000159 DM9000_DBG("\n");
160}
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200161#endif
162
163static void dm9000_outblk_8bit(void *data_ptr, int count)
164{
165 int i;
166 for (i = 0; i < count; i++)
167 DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
168}
169
170static void dm9000_outblk_16bit(void *data_ptr, int count)
171{
172 int i;
173 u32 tmplen = (count + 1) / 2;
174
175 for (i = 0; i < tmplen; i++)
176 DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
177}
178static void dm9000_outblk_32bit(void *data_ptr, int count)
179{
180 int i;
181 u32 tmplen = (count + 3) / 4;
182
183 for (i = 0; i < tmplen; i++)
184 DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
185}
186
187static void dm9000_inblk_8bit(void *data_ptr, int count)
188{
189 int i;
190 for (i = 0; i < count; i++)
191 ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
192}
193
194static void dm9000_inblk_16bit(void *data_ptr, int count)
195{
196 int i;
197 u32 tmplen = (count + 1) / 2;
198
199 for (i = 0; i < tmplen; i++)
200 ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
201}
202static void dm9000_inblk_32bit(void *data_ptr, int count)
203{
204 int i;
205 u32 tmplen = (count + 3) / 4;
206
207 for (i = 0; i < tmplen; i++)
208 ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
209}
210
211static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
212{
213 u32 tmpdata = DM9000_inl(DM9000_DATA);
214
215 DM9000_outb(DM9000_MRCMD, DM9000_IO);
216
217 *RxStatus = tmpdata;
218 *RxLen = tmpdata >> 16;
219}
220
221static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
222{
223 DM9000_outb(DM9000_MRCMD, DM9000_IO);
224
225 *RxStatus = DM9000_inw(DM9000_DATA);
226 *RxLen = DM9000_inw(DM9000_DATA);
227}
228
229static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
230{
231 DM9000_outb(DM9000_MRCMD, DM9000_IO);
232
233 *RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
234 *RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
235}
wdenk7ac16102004-08-01 22:48:16 +0000236
237/*
238 Search DM9000 board, allocate space and register it
239*/
240int
241dm9000_probe(void)
242{
243 u32 id_val;
244 id_val = DM9000_ior(DM9000_VIDL);
245 id_val |= DM9000_ior(DM9000_VIDH) << 8;
246 id_val |= DM9000_ior(DM9000_PIDL) << 16;
247 id_val |= DM9000_ior(DM9000_PIDH) << 24;
248 if (id_val == DM9000_ID) {
249 printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
250 id_val);
251 return 0;
252 } else {
253 printf("dm9000 not found at 0x%08x id: 0x%08x\n",
254 CONFIG_DM9000_BASE, id_val);
255 return -1;
256 }
257}
258
259/* Set PHY operationg mode
260*/
261static void
262set_PHY_mode(void)
263{
264 u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000;
265 if (!(media_mode & DM9000_AUTO)) {
266 switch (media_mode) {
267 case DM9000_10MHD:
268 phy_reg4 = 0x21;
269 phy_reg0 = 0x0000;
270 break;
271 case DM9000_10MFD:
272 phy_reg4 = 0x41;
273 phy_reg0 = 0x1100;
274 break;
275 case DM9000_100MHD:
276 phy_reg4 = 0x81;
277 phy_reg0 = 0x2000;
278 break;
279 case DM9000_100MFD:
280 phy_reg4 = 0x101;
281 phy_reg0 = 0x3100;
282 break;
283 }
284 phy_write(4, phy_reg4); /* Set PHY media mode */
285 phy_write(0, phy_reg0); /* Tmp */
286 }
287 DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */
288 DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */
289}
290
291/*
292 Init HomeRun DM9801
293*/
294static void
295program_dm9801(u16 HPNA_rev)
296{
297 __u16 reg16, reg17, reg24, reg25;
298 if (!nfloor)
299 nfloor = DM9801_NOISE_FLOOR;
300 reg16 = phy_read(16);
301 reg17 = phy_read(17);
302 reg24 = phy_read(24);
303 reg25 = phy_read(25);
304 switch (HPNA_rev) {
305 case 0xb900: /* DM9801 E3 */
306 reg16 |= 0x1000;
307 reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000;
308 break;
309 case 0xb901: /* DM9801 E4 */
310 reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200;
311 reg17 = (reg17 & 0xfff0) + nfloor + 3;
312 break;
313 case 0xb902: /* DM9801 E5 */
314 case 0xb903: /* DM9801 E6 */
315 default:
316 reg16 |= 0x1000;
317 reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200;
318 reg17 = (reg17 & 0xfff0) + nfloor;
319 }
320 phy_write(16, reg16);
321 phy_write(17, reg17);
322 phy_write(25, reg25);
323}
324
325/*
326 Init LongRun DM9802
327*/
328static void
329program_dm9802(void)
330{
331 __u16 reg25;
332 if (!nfloor)
333 nfloor = DM9802_NOISE_FLOOR;
334 reg25 = phy_read(25);
335 reg25 = (reg25 & 0xff00) + nfloor;
336 phy_write(25, reg25);
337}
338
339/* Identify NIC type
340*/
341static void
342identify_nic(void)
343{
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200344 struct board_info *db = &dm9000_info;
wdenk7ac16102004-08-01 22:48:16 +0000345 u16 phy_reg3;
346 DM9000_iow(DM9000_NCR, NCR_EXT_PHY);
347 phy_reg3 = phy_read(3);
348 switch (phy_reg3 & 0xfff0) {
349 case 0xb900:
350 if (phy_read(31) == 0x4404) {
351 db->nic_type = HOMERUN_NIC;
352 program_dm9801(phy_reg3);
353 DM9000_DBG("found homerun NIC\n");
354 } else {
355 db->nic_type = LONGRUN_NIC;
356 DM9000_DBG("found longrun NIC\n");
357 program_dm9802();
358 }
359 break;
360 default:
361 db->nic_type = FASTETHER_NIC;
362 break;
363 }
364 DM9000_iow(DM9000_NCR, 0);
365}
366
367/* General Purpose dm9000 reset routine */
368static void
369dm9000_reset(void)
370{
Remy Bohmer2f13d2c2008-06-03 15:26:24 +0200371 DM9000_DBG("resetting DM9000\n");
372
373 /* Reset DM9000,
374 see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
375
376 /* DEBUG: Make all GPIO pins outputs */
377 DM9000_iow(DM9000_GPCR, 0x0F);
378 /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
379 DM9000_iow(DM9000_GPR, 0);
380 /* Step 2: Software reset */
381 DM9000_iow(DM9000_NCR, 3);
382
383 do {
384 DM9000_DBG("resetting the DM9000, 1st reset\n");
385 udelay(25); /* Wait at least 20 us */
386 } while (DM9000_ior(DM9000_NCR) & 1);
387
388 DM9000_iow(DM9000_NCR, 0);
389 DM9000_iow(DM9000_NCR, 3); /* Issue a second reset */
390
391 do {
392 DM9000_DBG("resetting the DM9000, 2nd reset\n");
393 udelay(25); /* Wait at least 20 us */
394 } while (DM9000_ior(DM9000_NCR) & 1);
395
396 /* Check whether the ethernet controller is present */
397 if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
398 (DM9000_ior(DM9000_PIDH) != 0x90))
399 printf("ERROR: resetting DM9000 -> not responding\n");
wdenk7ac16102004-08-01 22:48:16 +0000400}
401
402/* Initilize dm9000 board
403*/
404int
405eth_init(bd_t * bd)
406{
407 int i, oft, lnk;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200408 u8 io_mode;
409 struct board_info *db = &dm9000_info;
410
wdenk7ac16102004-08-01 22:48:16 +0000411 DM9000_DBG("eth_init()\n");
412
413 /* RESET device */
414 dm9000_reset();
415 dm9000_probe();
416
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200417 /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
418 io_mode = DM9000_ior(DM9000_ISR) >> 6;
419
420 switch (io_mode) {
421 case 0x0: /* 16-bit mode */
422 printf("DM9000: running in 16 bit mode\n");
423 db->outblk = dm9000_outblk_16bit;
424 db->inblk = dm9000_inblk_16bit;
425 db->rx_status = dm9000_rx_status_16bit;
426 break;
427 case 0x01: /* 32-bit mode */
428 printf("DM9000: running in 32 bit mode\n");
429 db->outblk = dm9000_outblk_32bit;
430 db->inblk = dm9000_inblk_32bit;
431 db->rx_status = dm9000_rx_status_32bit;
432 break;
433 case 0x02: /* 8 bit mode */
434 printf("DM9000: running in 8 bit mode\n");
435 db->outblk = dm9000_outblk_8bit;
436 db->inblk = dm9000_inblk_8bit;
437 db->rx_status = dm9000_rx_status_8bit;
438 break;
439 default:
440 /* Assume 8 bit mode, will probably not work anyway */
441 printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
442 db->outblk = dm9000_outblk_8bit;
443 db->inblk = dm9000_inblk_8bit;
444 db->rx_status = dm9000_rx_status_8bit;
445 break;
446 }
447
wdenk7ac16102004-08-01 22:48:16 +0000448 /* NIC Type: FASTETHER, HOMERUN, LONGRUN */
449 identify_nic();
450
451 /* GPIO0 on pre-activate PHY */
452 DM9000_iow(DM9000_GPR, 0x00); /*REG_1F bit0 activate phyxcer */
453
454 /* Set PHY */
455 set_PHY_mode();
456
457 /* Program operating register */
458 DM9000_iow(DM9000_NCR, 0x0); /* only intern phy supported by now */
459 DM9000_iow(DM9000_TCR, 0); /* TX Polling clear */
460 DM9000_iow(DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */
461 DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8)); /* Flow Control : High/Low Water */
462 DM9000_iow(DM9000_FCR, 0x0); /* SH FIXME: This looks strange! Flow Control */
463 DM9000_iow(DM9000_SMCR, 0); /* Special Mode */
464 DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); /* clear TX status */
465 DM9000_iow(DM9000_ISR, 0x0f); /* Clear interrupt status */
466
467 /* Set Node address */
468 for (i = 0; i < 6; i++)
469 ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
Mike Rapoporte54d6c12007-08-12 08:48:27 +0300470
stefano babicedb06872007-08-21 15:50:33 +0200471 if (is_zero_ether_addr(bd->bi_enetaddr) ||
472 is_multicast_ether_addr(bd->bi_enetaddr)) {
Mike Rapoporte54d6c12007-08-12 08:48:27 +0300473 /* try reading from environment */
474 u8 i;
475 char *s, *e;
476 s = getenv ("ethaddr");
477 for (i = 0; i < 6; ++i) {
478 bd->bi_enetaddr[i] = s ?
479 simple_strtoul (s, &e, 16) : 0;
480 if (s)
481 s = (*e) ? e + 1 : e;
482 }
483 }
484
wdenk7ac16102004-08-01 22:48:16 +0000485 printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
486 bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
487 bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
488 for (i = 0, oft = 0x10; i < 6; i++, oft++)
489 DM9000_iow(oft, bd->bi_enetaddr[i]);
490 for (i = 0, oft = 0x16; i < 8; i++, oft++)
491 DM9000_iow(oft, 0xff);
492
493 /* read back mac, just to be sure */
494 for (i = 0, oft = 0x10; i < 6; i++, oft++)
495 DM9000_DBG("%02x:", DM9000_ior(oft));
496 DM9000_DBG("\n");
497
498 /* Activate DM9000 */
499 DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */
500 DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */
501 i = 0;
502 while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
503 udelay(1000);
504 i++;
505 if (i == 10000) {
506 printf("could not establish link\n");
507 return 0;
508 }
509 }
510
511 /* see what we've got */
512 lnk = phy_read(17) >> 12;
513 printf("operating at ");
514 switch (lnk) {
515 case 1:
516 printf("10M half duplex ");
517 break;
518 case 2:
519 printf("10M full duplex ");
520 break;
521 case 4:
522 printf("100M half duplex ");
523 break;
524 case 8:
525 printf("100M full duplex ");
526 break;
527 default:
528 printf("unknown: %d ", lnk);
529 break;
530 }
531 printf("mode\n");
532 return 0;
533}
534
535/*
536 Hardware start transmission.
537 Send a packet to media from the upper layer.
538*/
539int
540eth_send(volatile void *packet, int length)
541{
542 char *data_ptr;
wdenk7ac16102004-08-01 22:48:16 +0000543 int tmo;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200544 struct board_info *db = &dm9000_info;
545
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200546 DM9000_DMP_PACKET("eth_send", packet, length);
wdenk7ac16102004-08-01 22:48:16 +0000547
Remy Bohmer16cb2642008-06-03 15:26:23 +0200548 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
549
wdenk7ac16102004-08-01 22:48:16 +0000550 /* Move data to DM9000 TX RAM */
551 data_ptr = (char *) packet;
Remy Bohmer16cb2642008-06-03 15:26:23 +0200552 DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
wdenk7ac16102004-08-01 22:48:16 +0000553
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200554 /* push the data to the TX-fifo */
555 (db->outblk)(data_ptr, length);
wdenk7ac16102004-08-01 22:48:16 +0000556
557 /* Set TX length to DM9000 */
558 DM9000_iow(DM9000_TXPLL, length & 0xff);
559 DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
560
561 /* Issue TX polling command */
Remy Bohmer16cb2642008-06-03 15:26:23 +0200562 DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
wdenk7ac16102004-08-01 22:48:16 +0000563
564 /* wait for end of transmission */
565 tmo = get_timer(0) + 5 * CFG_HZ;
Remy Bohmer16cb2642008-06-03 15:26:23 +0200566 while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
567 !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
wdenk7ac16102004-08-01 22:48:16 +0000568 if (get_timer(0) >= tmo) {
569 printf("transmission timeout\n");
570 break;
571 }
572 }
Remy Bohmer16cb2642008-06-03 15:26:23 +0200573 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
574
wdenk7ac16102004-08-01 22:48:16 +0000575 DM9000_DBG("transmit done\n\n");
576 return 0;
577}
578
579/*
580 Stop the interface.
581 The interface is stopped when it is brought.
582*/
583void
584eth_halt(void)
585{
586 DM9000_DBG("eth_halt\n");
587
588 /* RESET devie */
589 phy_write(0, 0x8000); /* PHY RESET */
590 DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
591 DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
592 DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
593}
594
595/*
596 Received a packet and pass to upper layer
597*/
598int
599eth_rx(void)
600{
601 u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
602 u16 RxStatus, RxLen = 0;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200603 struct board_info *db = &dm9000_info;
wdenk7ac16102004-08-01 22:48:16 +0000604
Remy Bohmereec38a12008-06-03 15:26:25 +0200605 /* Check packet ready or not, we must check
606 the ISR status first for DM9000A */
607 if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
wdenk7ac16102004-08-01 22:48:16 +0000608 return 0;
609
Remy Bohmereec38a12008-06-03 15:26:25 +0200610 DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
wdenk7ac16102004-08-01 22:48:16 +0000611
Remy Bohmereec38a12008-06-03 15:26:25 +0200612 /* There is _at least_ 1 package in the fifo, read them all */
613 for (;;) {
614 DM9000_ior(DM9000_MRCMDX); /* Dummy read */
wdenk7ac16102004-08-01 22:48:16 +0000615
Remy Bohmereec38a12008-06-03 15:26:25 +0200616 /* Get most updated data */
617 rxbyte = DM9000_inb(DM9000_DATA);
wdenk7ac16102004-08-01 22:48:16 +0000618
Remy Bohmereec38a12008-06-03 15:26:25 +0200619 /* Status check: this byte must be 0 or 1 */
620 if (rxbyte > DM9000_PKT_RDY) {
621 DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
622 DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
623 printf("DM9000 error: status check fail: 0x%x\n",
624 rxbyte);
625 return 0;
626 }
wdenk7ac16102004-08-01 22:48:16 +0000627
Remy Bohmereec38a12008-06-03 15:26:25 +0200628 if (rxbyte != DM9000_PKT_RDY)
629 return 0; /* No packet received, ignore */
wdenk7ac16102004-08-01 22:48:16 +0000630
Remy Bohmereec38a12008-06-03 15:26:25 +0200631 DM9000_DBG("receiving packet\n");
632
633 /* A packet ready now & Get status/length */
634 (db->rx_status)(&RxStatus, &RxLen);
wdenk7ac16102004-08-01 22:48:16 +0000635
Remy Bohmereec38a12008-06-03 15:26:25 +0200636 DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
637
638 /* Move data from DM9000 */
639 /* Read received packet from RX SRAM */
640 (db->inblk)(rdptr, RxLen);
641
642 if ((RxStatus & 0xbf00) || (RxLen < 0x40)
643 || (RxLen > DM9000_PKT_MAX)) {
644 if (RxStatus & 0x100) {
645 printf("rx fifo error\n");
646 }
647 if (RxStatus & 0x200) {
648 printf("rx crc error\n");
649 }
650 if (RxStatus & 0x8000) {
651 printf("rx length error\n");
652 }
653 if (RxLen > DM9000_PKT_MAX) {
654 printf("rx length too big\n");
655 dm9000_reset();
656 }
657 } else {
658 DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
659
660 DM9000_DBG("passing packet to upper layer\n");
661 NetReceive(NetRxPackets[0], RxLen);
662 }
wdenk7ac16102004-08-01 22:48:16 +0000663 }
664 return 0;
665}
666
667/*
668 Read a word data from SROM
669*/
stefano babic6708a602007-08-30 23:01:49 +0200670u16
wdenk7ac16102004-08-01 22:48:16 +0000671read_srom_word(int offset)
672{
673 DM9000_iow(DM9000_EPAR, offset);
674 DM9000_iow(DM9000_EPCR, 0x4);
stefano babicedb06872007-08-21 15:50:33 +0200675 udelay(8000);
wdenk7ac16102004-08-01 22:48:16 +0000676 DM9000_iow(DM9000_EPCR, 0x0);
677 return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
678}
679
stefano babic6708a602007-08-30 23:01:49 +0200680void
681write_srom_word(int offset, u16 val)
682{
683 DM9000_iow(DM9000_EPAR, offset);
684 DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
685 DM9000_iow(DM9000_EPDRL, (val & 0xff));
686 DM9000_iow(DM9000_EPCR, 0x12);
687 udelay(8000);
688 DM9000_iow(DM9000_EPCR, 0);
689}
690
691
wdenk7ac16102004-08-01 22:48:16 +0000692/*
693 Read a byte from I/O port
694*/
695static u8
696DM9000_ior(int reg)
697{
698 DM9000_outb(reg, DM9000_IO);
699 return DM9000_inb(DM9000_DATA);
700}
701
702/*
703 Write a byte to I/O port
704*/
705static void
706DM9000_iow(int reg, u8 value)
707{
708 DM9000_outb(reg, DM9000_IO);
709 DM9000_outb(value, DM9000_DATA);
710}
711
712/*
713 Read a word from phyxcer
714*/
715static u16
716phy_read(int reg)
717{
718 u16 val;
719
720 /* Fill the phyxcer register into REG_0C */
721 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
722 DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
723 udelay(100); /* Wait read complete */
724 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
725 val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
726
727 /* The read data keeps on REG_0D & REG_0E */
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200728 DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
wdenk7ac16102004-08-01 22:48:16 +0000729 return val;
730}
731
732/*
733 Write a word to phyxcer
734*/
735static void
736phy_write(int reg, u16 value)
737{
738
739 /* Fill the phyxcer register into REG_0C */
740 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
741
742 /* Fill the written data into REG_0D & REG_0E */
743 DM9000_iow(DM9000_EPDRL, (value & 0xff));
744 DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
745 DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
746 udelay(500); /* Wait write complete */
747 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200748 DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
wdenk7ac16102004-08-01 22:48:16 +0000749}
750#endif /* CONFIG_DRIVER_DM9000 */