blob: 6f3ddf020dad1f643b853c86aa6f35b73a880428 [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 Bohmer61b8dbd2008-06-03 15:26:26 +020054 - some minor code cleanups
Remy Bohmer5f63bf42008-06-03 15:26:21 +020055 These changes are tested with DM9000{A,EP,E} together
56 with a 200MHz Atmel AT91SAM92161 core
wdenk7ac16102004-08-01 22:48:16 +000057
58TODO: Homerun NIC and longrun NIC are not functional, only internal at the
59 moment.
60*/
61
62#include <common.h>
63#include <command.h>
64#include <net.h>
65#include <asm/io.h>
66
67#ifdef CONFIG_DRIVER_DM9000
68
69#include "dm9000x.h"
70
71/* Board/System/Debug information/definition ---------------- */
72
73#define DM9801_NOISE_FLOOR 0x08
74#define DM9802_NOISE_FLOOR 0x05
75
76/* #define CONFIG_DM9000_DEBUG */
77
78#ifdef CONFIG_DM9000_DEBUG
Remy Bohmerf4329dc2008-06-03 15:26:22 +020079#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
80#define DM9000_DMP_PACKET(func,packet,length) \
81 do { \
82 int i; \
83 printf(func ": length: %d\n", length); \
84 for (i = 0; i < length; i++) { \
85 if (i % 8 == 0) \
86 printf("\n%s: %02x: ", func, i); \
87 printf("%02x ", ((unsigned char *) packet)[i]); \
88 } printf("\n"); \
89 } while(0)
90#else
wdenk7ac16102004-08-01 22:48:16 +000091#define DM9000_DBG(fmt,args...)
Remy Bohmerf4329dc2008-06-03 15:26:22 +020092#define DM9000_DMP_PACKET(func,packet,length)
93#endif
94
wdenk7ac16102004-08-01 22:48:16 +000095enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD =
96 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO =
97 8, DM9000_1M_HPNA = 0x10
98};
99enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2
100};
101
102/* Structure/enum declaration ------------------------------- */
103typedef struct board_info {
104 u32 runt_length_counter; /* counter: RX length < 64byte */
105 u32 long_length_counter; /* counter: RX length > 1514byte */
106 u32 reset_counter; /* counter: RESET */
107 u32 reset_tx_timeout; /* RESET caused by TX Timeout */
108 u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
109 u16 tx_pkt_cnt;
110 u16 queue_start_addr;
111 u16 dbug_cnt;
112 u8 phy_addr;
113 u8 device_wait_reset; /* device state */
114 u8 nic_type; /* NIC type */
115 unsigned char srom[128];
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200116 void (*outblk)(void *data_ptr, int count);
117 void (*inblk)(void *data_ptr, int count);
118 void (*rx_status)(u16 *RxStatus, u16 *RxLen);
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200119} board_info_t;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200120static board_info_t dm9000_info;
wdenk7ac16102004-08-01 22:48:16 +0000121
122/* For module input parameter */
123static int media_mode = DM9000_AUTO;
124static u8 nfloor = 0;
125
126/* function declaration ------------------------------------- */
127int eth_init(bd_t * bd);
128int eth_send(volatile void *, int);
129int eth_rx(void);
130void eth_halt(void);
131static int dm9000_probe(void);
132static u16 phy_read(int);
133static void phy_write(int, u16);
stefano babic6708a602007-08-30 23:01:49 +0200134u16 read_srom_word(int);
wdenk7ac16102004-08-01 22:48:16 +0000135static u8 DM9000_ior(int);
136static void DM9000_iow(int reg, u8 value);
137
138/* DM9000 network board routine ---------------------------- */
139
140#define DM9000_outb(d,r) ( *(volatile u8 *)r = d )
141#define DM9000_outw(d,r) ( *(volatile u16 *)r = d )
142#define DM9000_outl(d,r) ( *(volatile u32 *)r = d )
143#define DM9000_inb(r) (*(volatile u8 *)r)
144#define DM9000_inw(r) (*(volatile u16 *)r)
145#define DM9000_inl(r) (*(volatile u32 *)r)
146
147#ifdef CONFIG_DM9000_DEBUG
148static void
149dump_regs(void)
150{
151 DM9000_DBG("\n");
152 DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0));
153 DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1));
154 DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2));
155 DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3));
156 DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
157 DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
158 DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200159 DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
wdenk7ac16102004-08-01 22:48:16 +0000160 DM9000_DBG("\n");
161}
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200162#endif
163
164static void dm9000_outblk_8bit(void *data_ptr, int count)
165{
166 int i;
167 for (i = 0; i < count; i++)
168 DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
169}
170
171static void dm9000_outblk_16bit(void *data_ptr, int count)
172{
173 int i;
174 u32 tmplen = (count + 1) / 2;
175
176 for (i = 0; i < tmplen; i++)
177 DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
178}
179static void dm9000_outblk_32bit(void *data_ptr, int count)
180{
181 int i;
182 u32 tmplen = (count + 3) / 4;
183
184 for (i = 0; i < tmplen; i++)
185 DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
186}
187
188static void dm9000_inblk_8bit(void *data_ptr, int count)
189{
190 int i;
191 for (i = 0; i < count; i++)
192 ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
193}
194
195static void dm9000_inblk_16bit(void *data_ptr, int count)
196{
197 int i;
198 u32 tmplen = (count + 1) / 2;
199
200 for (i = 0; i < tmplen; i++)
201 ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
202}
203static void dm9000_inblk_32bit(void *data_ptr, int count)
204{
205 int i;
206 u32 tmplen = (count + 3) / 4;
207
208 for (i = 0; i < tmplen; i++)
209 ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
210}
211
212static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
213{
Remy Bohmer2e1604f2008-06-04 10:47:25 +0200214 u32 tmpdata;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200215
216 DM9000_outb(DM9000_MRCMD, DM9000_IO);
217
Remy Bohmer2e1604f2008-06-04 10:47:25 +0200218 tmpdata = DM9000_inl(DM9000_DATA);
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200219 *RxStatus = tmpdata;
220 *RxLen = tmpdata >> 16;
221}
222
223static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
224{
225 DM9000_outb(DM9000_MRCMD, DM9000_IO);
226
227 *RxStatus = DM9000_inw(DM9000_DATA);
228 *RxLen = DM9000_inw(DM9000_DATA);
229}
230
231static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
232{
233 DM9000_outb(DM9000_MRCMD, DM9000_IO);
234
235 *RxStatus = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
236 *RxLen = DM9000_inb(DM9000_DATA) + (DM9000_inb(DM9000_DATA) << 8);
237}
wdenk7ac16102004-08-01 22:48:16 +0000238
239/*
240 Search DM9000 board, allocate space and register it
241*/
242int
243dm9000_probe(void)
244{
245 u32 id_val;
246 id_val = DM9000_ior(DM9000_VIDL);
247 id_val |= DM9000_ior(DM9000_VIDH) << 8;
248 id_val |= DM9000_ior(DM9000_PIDL) << 16;
249 id_val |= DM9000_ior(DM9000_PIDH) << 24;
250 if (id_val == DM9000_ID) {
251 printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
252 id_val);
253 return 0;
254 } else {
255 printf("dm9000 not found at 0x%08x id: 0x%08x\n",
256 CONFIG_DM9000_BASE, id_val);
257 return -1;
258 }
259}
260
261/* Set PHY operationg mode
262*/
263static void
264set_PHY_mode(void)
265{
266 u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000;
267 if (!(media_mode & DM9000_AUTO)) {
268 switch (media_mode) {
269 case DM9000_10MHD:
270 phy_reg4 = 0x21;
271 phy_reg0 = 0x0000;
272 break;
273 case DM9000_10MFD:
274 phy_reg4 = 0x41;
275 phy_reg0 = 0x1100;
276 break;
277 case DM9000_100MHD:
278 phy_reg4 = 0x81;
279 phy_reg0 = 0x2000;
280 break;
281 case DM9000_100MFD:
282 phy_reg4 = 0x101;
283 phy_reg0 = 0x3100;
284 break;
285 }
286 phy_write(4, phy_reg4); /* Set PHY media mode */
287 phy_write(0, phy_reg0); /* Tmp */
288 }
289 DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */
290 DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */
291}
292
293/*
294 Init HomeRun DM9801
295*/
296static void
297program_dm9801(u16 HPNA_rev)
298{
299 __u16 reg16, reg17, reg24, reg25;
300 if (!nfloor)
301 nfloor = DM9801_NOISE_FLOOR;
302 reg16 = phy_read(16);
303 reg17 = phy_read(17);
304 reg24 = phy_read(24);
305 reg25 = phy_read(25);
306 switch (HPNA_rev) {
307 case 0xb900: /* DM9801 E3 */
308 reg16 |= 0x1000;
309 reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000;
310 break;
311 case 0xb901: /* DM9801 E4 */
312 reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200;
313 reg17 = (reg17 & 0xfff0) + nfloor + 3;
314 break;
315 case 0xb902: /* DM9801 E5 */
316 case 0xb903: /* DM9801 E6 */
317 default:
318 reg16 |= 0x1000;
319 reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200;
320 reg17 = (reg17 & 0xfff0) + nfloor;
321 }
322 phy_write(16, reg16);
323 phy_write(17, reg17);
324 phy_write(25, reg25);
325}
326
327/*
328 Init LongRun DM9802
329*/
330static void
331program_dm9802(void)
332{
333 __u16 reg25;
334 if (!nfloor)
335 nfloor = DM9802_NOISE_FLOOR;
336 reg25 = phy_read(25);
337 reg25 = (reg25 & 0xff00) + nfloor;
338 phy_write(25, reg25);
339}
340
341/* Identify NIC type
342*/
343static void
344identify_nic(void)
345{
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200346 struct board_info *db = &dm9000_info;
wdenk7ac16102004-08-01 22:48:16 +0000347 u16 phy_reg3;
348 DM9000_iow(DM9000_NCR, NCR_EXT_PHY);
349 phy_reg3 = phy_read(3);
350 switch (phy_reg3 & 0xfff0) {
351 case 0xb900:
352 if (phy_read(31) == 0x4404) {
353 db->nic_type = HOMERUN_NIC;
354 program_dm9801(phy_reg3);
355 DM9000_DBG("found homerun NIC\n");
356 } else {
357 db->nic_type = LONGRUN_NIC;
358 DM9000_DBG("found longrun NIC\n");
359 program_dm9802();
360 }
361 break;
362 default:
363 db->nic_type = FASTETHER_NIC;
364 break;
365 }
366 DM9000_iow(DM9000_NCR, 0);
367}
368
369/* General Purpose dm9000 reset routine */
370static void
371dm9000_reset(void)
372{
Remy Bohmer2f13d2c2008-06-03 15:26:24 +0200373 DM9000_DBG("resetting DM9000\n");
374
375 /* Reset DM9000,
376 see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
377
378 /* DEBUG: Make all GPIO pins outputs */
379 DM9000_iow(DM9000_GPCR, 0x0F);
380 /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
381 DM9000_iow(DM9000_GPR, 0);
382 /* Step 2: Software reset */
383 DM9000_iow(DM9000_NCR, 3);
384
385 do {
386 DM9000_DBG("resetting the DM9000, 1st reset\n");
387 udelay(25); /* Wait at least 20 us */
388 } while (DM9000_ior(DM9000_NCR) & 1);
389
390 DM9000_iow(DM9000_NCR, 0);
391 DM9000_iow(DM9000_NCR, 3); /* Issue a second reset */
392
393 do {
394 DM9000_DBG("resetting the DM9000, 2nd reset\n");
395 udelay(25); /* Wait at least 20 us */
396 } while (DM9000_ior(DM9000_NCR) & 1);
397
398 /* Check whether the ethernet controller is present */
399 if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
400 (DM9000_ior(DM9000_PIDH) != 0x90))
401 printf("ERROR: resetting DM9000 -> not responding\n");
wdenk7ac16102004-08-01 22:48:16 +0000402}
403
404/* Initilize dm9000 board
405*/
406int
407eth_init(bd_t * bd)
408{
409 int i, oft, lnk;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200410 u8 io_mode;
411 struct board_info *db = &dm9000_info;
412
wdenk7ac16102004-08-01 22:48:16 +0000413 DM9000_DBG("eth_init()\n");
414
415 /* RESET device */
416 dm9000_reset();
417 dm9000_probe();
418
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200419 /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
420 io_mode = DM9000_ior(DM9000_ISR) >> 6;
421
422 switch (io_mode) {
423 case 0x0: /* 16-bit mode */
424 printf("DM9000: running in 16 bit mode\n");
425 db->outblk = dm9000_outblk_16bit;
426 db->inblk = dm9000_inblk_16bit;
427 db->rx_status = dm9000_rx_status_16bit;
428 break;
429 case 0x01: /* 32-bit mode */
430 printf("DM9000: running in 32 bit mode\n");
431 db->outblk = dm9000_outblk_32bit;
432 db->inblk = dm9000_inblk_32bit;
433 db->rx_status = dm9000_rx_status_32bit;
434 break;
435 case 0x02: /* 8 bit mode */
436 printf("DM9000: running in 8 bit mode\n");
437 db->outblk = dm9000_outblk_8bit;
438 db->inblk = dm9000_inblk_8bit;
439 db->rx_status = dm9000_rx_status_8bit;
440 break;
441 default:
442 /* Assume 8 bit mode, will probably not work anyway */
443 printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
444 db->outblk = dm9000_outblk_8bit;
445 db->inblk = dm9000_inblk_8bit;
446 db->rx_status = dm9000_rx_status_8bit;
447 break;
448 }
449
wdenk7ac16102004-08-01 22:48:16 +0000450 /* NIC Type: FASTETHER, HOMERUN, LONGRUN */
451 identify_nic();
452
453 /* GPIO0 on pre-activate PHY */
454 DM9000_iow(DM9000_GPR, 0x00); /*REG_1F bit0 activate phyxcer */
455
456 /* Set PHY */
457 set_PHY_mode();
458
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200459 /* Program operating register, only intern phy supported by now */
460 DM9000_iow(DM9000_NCR, 0x0);
461 /* TX Polling clear */
462 DM9000_iow(DM9000_TCR, 0);
463 /* Less 3Kb, 200us */
464 DM9000_iow(DM9000_BPTR, 0x3f);
465 /* Flow Control : High/Low Water */
466 DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
467 /* SH FIXME: This looks strange! Flow Control */
468 DM9000_iow(DM9000_FCR, 0x0);
469 /* Special Mode */
470 DM9000_iow(DM9000_SMCR, 0);
471 /* clear TX status */
472 DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
473 /* Clear interrupt status */
474 DM9000_iow(DM9000_ISR, 0x0f);
wdenk7ac16102004-08-01 22:48:16 +0000475
476 /* Set Node address */
477 for (i = 0; i < 6; i++)
478 ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
Mike Rapoporte54d6c12007-08-12 08:48:27 +0300479
stefano babicedb06872007-08-21 15:50:33 +0200480 if (is_zero_ether_addr(bd->bi_enetaddr) ||
481 is_multicast_ether_addr(bd->bi_enetaddr)) {
Mike Rapoporte54d6c12007-08-12 08:48:27 +0300482 /* try reading from environment */
483 u8 i;
484 char *s, *e;
485 s = getenv ("ethaddr");
486 for (i = 0; i < 6; ++i) {
487 bd->bi_enetaddr[i] = s ?
488 simple_strtoul (s, &e, 16) : 0;
489 if (s)
490 s = (*e) ? e + 1 : e;
491 }
492 }
493
wdenk7ac16102004-08-01 22:48:16 +0000494 printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
495 bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
496 bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
497 for (i = 0, oft = 0x10; i < 6; i++, oft++)
498 DM9000_iow(oft, bd->bi_enetaddr[i]);
499 for (i = 0, oft = 0x16; i < 8; i++, oft++)
500 DM9000_iow(oft, 0xff);
501
502 /* read back mac, just to be sure */
503 for (i = 0, oft = 0x10; i < 6; i++, oft++)
504 DM9000_DBG("%02x:", DM9000_ior(oft));
505 DM9000_DBG("\n");
506
507 /* Activate DM9000 */
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200508 /* RX enable */
509 DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
510 /* Enable TX/RX interrupt mask */
511 DM9000_iow(DM9000_IMR, IMR_PAR);
512
wdenk7ac16102004-08-01 22:48:16 +0000513 i = 0;
514 while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
515 udelay(1000);
516 i++;
517 if (i == 10000) {
518 printf("could not establish link\n");
519 return 0;
520 }
521 }
522
523 /* see what we've got */
524 lnk = phy_read(17) >> 12;
525 printf("operating at ");
526 switch (lnk) {
527 case 1:
528 printf("10M half duplex ");
529 break;
530 case 2:
531 printf("10M full duplex ");
532 break;
533 case 4:
534 printf("100M half duplex ");
535 break;
536 case 8:
537 printf("100M full duplex ");
538 break;
539 default:
540 printf("unknown: %d ", lnk);
541 break;
542 }
543 printf("mode\n");
544 return 0;
545}
546
547/*
548 Hardware start transmission.
549 Send a packet to media from the upper layer.
550*/
551int
552eth_send(volatile void *packet, int length)
553{
554 char *data_ptr;
wdenk7ac16102004-08-01 22:48:16 +0000555 int tmo;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200556 struct board_info *db = &dm9000_info;
557
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200558 DM9000_DMP_PACKET("eth_send", packet, length);
wdenk7ac16102004-08-01 22:48:16 +0000559
Remy Bohmer16cb2642008-06-03 15:26:23 +0200560 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
561
wdenk7ac16102004-08-01 22:48:16 +0000562 /* Move data to DM9000 TX RAM */
563 data_ptr = (char *) packet;
Remy Bohmer16cb2642008-06-03 15:26:23 +0200564 DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
wdenk7ac16102004-08-01 22:48:16 +0000565
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200566 /* push the data to the TX-fifo */
567 (db->outblk)(data_ptr, length);
wdenk7ac16102004-08-01 22:48:16 +0000568
569 /* Set TX length to DM9000 */
570 DM9000_iow(DM9000_TXPLL, length & 0xff);
571 DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
572
573 /* Issue TX polling command */
Remy Bohmer16cb2642008-06-03 15:26:23 +0200574 DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
wdenk7ac16102004-08-01 22:48:16 +0000575
576 /* wait for end of transmission */
577 tmo = get_timer(0) + 5 * CFG_HZ;
Remy Bohmer16cb2642008-06-03 15:26:23 +0200578 while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
579 !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
wdenk7ac16102004-08-01 22:48:16 +0000580 if (get_timer(0) >= tmo) {
581 printf("transmission timeout\n");
582 break;
583 }
584 }
Remy Bohmer16cb2642008-06-03 15:26:23 +0200585 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
586
wdenk7ac16102004-08-01 22:48:16 +0000587 DM9000_DBG("transmit done\n\n");
588 return 0;
589}
590
591/*
592 Stop the interface.
593 The interface is stopped when it is brought.
594*/
595void
596eth_halt(void)
597{
598 DM9000_DBG("eth_halt\n");
599
600 /* RESET devie */
601 phy_write(0, 0x8000); /* PHY RESET */
602 DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
603 DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
604 DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
605}
606
607/*
608 Received a packet and pass to upper layer
609*/
610int
611eth_rx(void)
612{
613 u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
614 u16 RxStatus, RxLen = 0;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200615 struct board_info *db = &dm9000_info;
wdenk7ac16102004-08-01 22:48:16 +0000616
Remy Bohmereec38a12008-06-03 15:26:25 +0200617 /* Check packet ready or not, we must check
618 the ISR status first for DM9000A */
619 if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
wdenk7ac16102004-08-01 22:48:16 +0000620 return 0;
621
Remy Bohmereec38a12008-06-03 15:26:25 +0200622 DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
wdenk7ac16102004-08-01 22:48:16 +0000623
Remy Bohmereec38a12008-06-03 15:26:25 +0200624 /* There is _at least_ 1 package in the fifo, read them all */
625 for (;;) {
626 DM9000_ior(DM9000_MRCMDX); /* Dummy read */
wdenk7ac16102004-08-01 22:48:16 +0000627
Remy Bohmereec38a12008-06-03 15:26:25 +0200628 /* Get most updated data */
629 rxbyte = DM9000_inb(DM9000_DATA);
wdenk7ac16102004-08-01 22:48:16 +0000630
Remy Bohmereec38a12008-06-03 15:26:25 +0200631 /* Status check: this byte must be 0 or 1 */
632 if (rxbyte > DM9000_PKT_RDY) {
633 DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
634 DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
635 printf("DM9000 error: status check fail: 0x%x\n",
636 rxbyte);
637 return 0;
638 }
wdenk7ac16102004-08-01 22:48:16 +0000639
Remy Bohmereec38a12008-06-03 15:26:25 +0200640 if (rxbyte != DM9000_PKT_RDY)
641 return 0; /* No packet received, ignore */
wdenk7ac16102004-08-01 22:48:16 +0000642
Remy Bohmereec38a12008-06-03 15:26:25 +0200643 DM9000_DBG("receiving packet\n");
644
645 /* A packet ready now & Get status/length */
646 (db->rx_status)(&RxStatus, &RxLen);
wdenk7ac16102004-08-01 22:48:16 +0000647
Remy Bohmereec38a12008-06-03 15:26:25 +0200648 DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
649
650 /* Move data from DM9000 */
651 /* Read received packet from RX SRAM */
652 (db->inblk)(rdptr, RxLen);
653
654 if ((RxStatus & 0xbf00) || (RxLen < 0x40)
655 || (RxLen > DM9000_PKT_MAX)) {
656 if (RxStatus & 0x100) {
657 printf("rx fifo error\n");
658 }
659 if (RxStatus & 0x200) {
660 printf("rx crc error\n");
661 }
662 if (RxStatus & 0x8000) {
663 printf("rx length error\n");
664 }
665 if (RxLen > DM9000_PKT_MAX) {
666 printf("rx length too big\n");
667 dm9000_reset();
668 }
669 } else {
670 DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
671
672 DM9000_DBG("passing packet to upper layer\n");
673 NetReceive(NetRxPackets[0], RxLen);
674 }
wdenk7ac16102004-08-01 22:48:16 +0000675 }
676 return 0;
677}
678
679/*
680 Read a word data from SROM
681*/
stefano babic6708a602007-08-30 23:01:49 +0200682u16
wdenk7ac16102004-08-01 22:48:16 +0000683read_srom_word(int offset)
684{
685 DM9000_iow(DM9000_EPAR, offset);
686 DM9000_iow(DM9000_EPCR, 0x4);
stefano babicedb06872007-08-21 15:50:33 +0200687 udelay(8000);
wdenk7ac16102004-08-01 22:48:16 +0000688 DM9000_iow(DM9000_EPCR, 0x0);
689 return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
690}
691
stefano babic6708a602007-08-30 23:01:49 +0200692void
693write_srom_word(int offset, u16 val)
694{
695 DM9000_iow(DM9000_EPAR, offset);
696 DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
697 DM9000_iow(DM9000_EPDRL, (val & 0xff));
698 DM9000_iow(DM9000_EPCR, 0x12);
699 udelay(8000);
700 DM9000_iow(DM9000_EPCR, 0);
701}
702
703
wdenk7ac16102004-08-01 22:48:16 +0000704/*
705 Read a byte from I/O port
706*/
707static u8
708DM9000_ior(int reg)
709{
710 DM9000_outb(reg, DM9000_IO);
711 return DM9000_inb(DM9000_DATA);
712}
713
714/*
715 Write a byte to I/O port
716*/
717static void
718DM9000_iow(int reg, u8 value)
719{
720 DM9000_outb(reg, DM9000_IO);
721 DM9000_outb(value, DM9000_DATA);
722}
723
724/*
725 Read a word from phyxcer
726*/
727static u16
728phy_read(int reg)
729{
730 u16 val;
731
732 /* Fill the phyxcer register into REG_0C */
733 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
734 DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200735 udelay(100); /* Wait read complete */
wdenk7ac16102004-08-01 22:48:16 +0000736 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
737 val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
738
739 /* The read data keeps on REG_0D & REG_0E */
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200740 DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
wdenk7ac16102004-08-01 22:48:16 +0000741 return val;
742}
743
744/*
745 Write a word to phyxcer
746*/
747static void
748phy_write(int reg, u16 value)
749{
750
751 /* Fill the phyxcer register into REG_0C */
752 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
753
754 /* Fill the written data into REG_0D & REG_0E */
755 DM9000_iow(DM9000_EPDRL, (value & 0xff));
756 DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
757 DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200758 udelay(500); /* Wait write complete */
wdenk7ac16102004-08-01 22:48:16 +0000759 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200760 DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
wdenk7ac16102004-08-01 22:48:16 +0000761}
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200762#endif /* CONFIG_DRIVER_DM9000 */