blob: 844fb766d8c08edbbe9e686f6f631f46799be580 [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
wdenk7ac16102004-08-01 22:48:16 +000067#include "dm9000x.h"
68
69/* Board/System/Debug information/definition ---------------- */
70
71#define DM9801_NOISE_FLOOR 0x08
72#define DM9802_NOISE_FLOOR 0x05
73
74/* #define CONFIG_DM9000_DEBUG */
75
76#ifdef CONFIG_DM9000_DEBUG
Remy Bohmerf4329dc2008-06-03 15:26:22 +020077#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
78#define DM9000_DMP_PACKET(func,packet,length) \
79 do { \
80 int i; \
81 printf(func ": length: %d\n", length); \
82 for (i = 0; i < length; i++) { \
83 if (i % 8 == 0) \
84 printf("\n%s: %02x: ", func, i); \
85 printf("%02x ", ((unsigned char *) packet)[i]); \
86 } printf("\n"); \
87 } while(0)
88#else
wdenk7ac16102004-08-01 22:48:16 +000089#define DM9000_DBG(fmt,args...)
Remy Bohmerf4329dc2008-06-03 15:26:22 +020090#define DM9000_DMP_PACKET(func,packet,length)
91#endif
92
wdenk7ac16102004-08-01 22:48:16 +000093enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD =
94 1, DM9000_10MFD = 4, DM9000_100MFD = 5, DM9000_AUTO =
95 8, DM9000_1M_HPNA = 0x10
96};
97enum DM9000_NIC_TYPE { FASTETHER_NIC = 0, HOMERUN_NIC = 1, LONGRUN_NIC = 2
98};
99
100/* Structure/enum declaration ------------------------------- */
101typedef struct board_info {
102 u32 runt_length_counter; /* counter: RX length < 64byte */
103 u32 long_length_counter; /* counter: RX length > 1514byte */
104 u32 reset_counter; /* counter: RESET */
105 u32 reset_tx_timeout; /* RESET caused by TX Timeout */
106 u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
107 u16 tx_pkt_cnt;
108 u16 queue_start_addr;
109 u16 dbug_cnt;
110 u8 phy_addr;
111 u8 device_wait_reset; /* device state */
112 u8 nic_type; /* NIC type */
113 unsigned char srom[128];
Remy Bohmer90d1fed2008-06-05 13:03:36 +0200114 void (*outblk)(volatile void *data_ptr, int count);
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200115 void (*inblk)(void *data_ptr, int count);
116 void (*rx_status)(u16 *RxStatus, u16 *RxLen);
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200117} board_info_t;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200118static board_info_t dm9000_info;
wdenk7ac16102004-08-01 22:48:16 +0000119
120/* For module input parameter */
121static int media_mode = DM9000_AUTO;
122static u8 nfloor = 0;
123
124/* function declaration ------------------------------------- */
125int eth_init(bd_t * bd);
126int eth_send(volatile void *, int);
127int eth_rx(void);
128void eth_halt(void);
129static int dm9000_probe(void);
130static u16 phy_read(int);
131static void phy_write(int, u16);
stefano babic6708a602007-08-30 23:01:49 +0200132u16 read_srom_word(int);
wdenk7ac16102004-08-01 22:48:16 +0000133static u8 DM9000_ior(int);
134static void DM9000_iow(int reg, u8 value);
135
136/* DM9000 network board routine ---------------------------- */
137
138#define DM9000_outb(d,r) ( *(volatile u8 *)r = d )
139#define DM9000_outw(d,r) ( *(volatile u16 *)r = d )
140#define DM9000_outl(d,r) ( *(volatile u32 *)r = d )
141#define DM9000_inb(r) (*(volatile u8 *)r)
142#define DM9000_inw(r) (*(volatile u16 *)r)
143#define DM9000_inl(r) (*(volatile u32 *)r)
144
145#ifdef CONFIG_DM9000_DEBUG
146static void
147dump_regs(void)
148{
149 DM9000_DBG("\n");
150 DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0));
151 DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1));
152 DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2));
153 DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3));
154 DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
155 DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
156 DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200157 DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
wdenk7ac16102004-08-01 22:48:16 +0000158 DM9000_DBG("\n");
159}
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200160#endif
161
Remy Bohmer90d1fed2008-06-05 13:03:36 +0200162static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200163{
164 int i;
165 for (i = 0; i < count; i++)
166 DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
167}
168
Remy Bohmer90d1fed2008-06-05 13:03:36 +0200169static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200170{
171 int i;
172 u32 tmplen = (count + 1) / 2;
173
174 for (i = 0; i < tmplen; i++)
175 DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
176}
Remy Bohmer90d1fed2008-06-05 13:03:36 +0200177static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200178{
179 int i;
180 u32 tmplen = (count + 3) / 4;
181
182 for (i = 0; i < tmplen; i++)
183 DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
184}
185
186static void dm9000_inblk_8bit(void *data_ptr, int count)
187{
188 int i;
189 for (i = 0; i < count; i++)
190 ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
191}
192
193static void dm9000_inblk_16bit(void *data_ptr, int count)
194{
195 int i;
196 u32 tmplen = (count + 1) / 2;
197
198 for (i = 0; i < tmplen; i++)
199 ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
200}
201static void dm9000_inblk_32bit(void *data_ptr, int count)
202{
203 int i;
204 u32 tmplen = (count + 3) / 4;
205
206 for (i = 0; i < tmplen; i++)
207 ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
208}
209
210static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
211{
Remy Bohmer2e1604f2008-06-04 10:47:25 +0200212 u32 tmpdata;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200213
214 DM9000_outb(DM9000_MRCMD, DM9000_IO);
215
Remy Bohmer2e1604f2008-06-04 10:47:25 +0200216 tmpdata = DM9000_inl(DM9000_DATA);
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200217 *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
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200457 /* Program operating register, only intern phy supported by now */
458 DM9000_iow(DM9000_NCR, 0x0);
459 /* TX Polling clear */
460 DM9000_iow(DM9000_TCR, 0);
461 /* Less 3Kb, 200us */
462 DM9000_iow(DM9000_BPTR, 0x3f);
463 /* Flow Control : High/Low Water */
464 DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
465 /* SH FIXME: This looks strange! Flow Control */
466 DM9000_iow(DM9000_FCR, 0x0);
467 /* Special Mode */
468 DM9000_iow(DM9000_SMCR, 0);
469 /* clear TX status */
470 DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
471 /* Clear interrupt status */
472 DM9000_iow(DM9000_ISR, 0x0f);
wdenk7ac16102004-08-01 22:48:16 +0000473
474 /* Set Node address */
Stelian Pop61e69d72008-05-08 20:52:22 +0200475#ifndef CONFIG_AT91SAM9261EK
wdenk7ac16102004-08-01 22:48:16 +0000476 for (i = 0; i < 6; i++)
477 ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
Stelian Pop61e69d72008-05-08 20:52:22 +0200478#endif
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{
wdenk7ac16102004-08-01 22:48:16 +0000554 int tmo;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200555 struct board_info *db = &dm9000_info;
556
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200557 DM9000_DMP_PACKET("eth_send", packet, length);
wdenk7ac16102004-08-01 22:48:16 +0000558
Remy Bohmer16cb2642008-06-03 15:26:23 +0200559 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
560
wdenk7ac16102004-08-01 22:48:16 +0000561 /* Move data to DM9000 TX RAM */
Remy Bohmer16cb2642008-06-03 15:26:23 +0200562 DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
wdenk7ac16102004-08-01 22:48:16 +0000563
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200564 /* push the data to the TX-fifo */
Remy Bohmer90d1fed2008-06-05 13:03:36 +0200565 (db->outblk)(packet, length);
wdenk7ac16102004-08-01 22:48:16 +0000566
567 /* Set TX length to DM9000 */
568 DM9000_iow(DM9000_TXPLL, length & 0xff);
569 DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
570
571 /* Issue TX polling command */
Remy Bohmer16cb2642008-06-03 15:26:23 +0200572 DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
wdenk7ac16102004-08-01 22:48:16 +0000573
574 /* wait for end of transmission */
575 tmo = get_timer(0) + 5 * CFG_HZ;
Remy Bohmer16cb2642008-06-03 15:26:23 +0200576 while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
577 !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
wdenk7ac16102004-08-01 22:48:16 +0000578 if (get_timer(0) >= tmo) {
579 printf("transmission timeout\n");
580 break;
581 }
582 }
Remy Bohmer16cb2642008-06-03 15:26:23 +0200583 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
584
wdenk7ac16102004-08-01 22:48:16 +0000585 DM9000_DBG("transmit done\n\n");
586 return 0;
587}
588
589/*
590 Stop the interface.
591 The interface is stopped when it is brought.
592*/
593void
594eth_halt(void)
595{
596 DM9000_DBG("eth_halt\n");
597
598 /* RESET devie */
599 phy_write(0, 0x8000); /* PHY RESET */
600 DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
601 DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
602 DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
603}
604
605/*
606 Received a packet and pass to upper layer
607*/
608int
609eth_rx(void)
610{
611 u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
612 u16 RxStatus, RxLen = 0;
Remy Bohmer5f63bf42008-06-03 15:26:21 +0200613 struct board_info *db = &dm9000_info;
wdenk7ac16102004-08-01 22:48:16 +0000614
Remy Bohmereec38a12008-06-03 15:26:25 +0200615 /* Check packet ready or not, we must check
616 the ISR status first for DM9000A */
617 if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
wdenk7ac16102004-08-01 22:48:16 +0000618 return 0;
619
Remy Bohmereec38a12008-06-03 15:26:25 +0200620 DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
wdenk7ac16102004-08-01 22:48:16 +0000621
Remy Bohmereec38a12008-06-03 15:26:25 +0200622 /* There is _at least_ 1 package in the fifo, read them all */
623 for (;;) {
624 DM9000_ior(DM9000_MRCMDX); /* Dummy read */
wdenk7ac16102004-08-01 22:48:16 +0000625
Remy Bohmer90d1fed2008-06-05 13:03:36 +0200626 /* Get most updated data,
627 only look at bits 0:1, See application notes DM9000 */
628 rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
wdenk7ac16102004-08-01 22:48:16 +0000629
Remy Bohmereec38a12008-06-03 15:26:25 +0200630 /* Status check: this byte must be 0 or 1 */
631 if (rxbyte > DM9000_PKT_RDY) {
632 DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
633 DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
634 printf("DM9000 error: status check fail: 0x%x\n",
635 rxbyte);
636 return 0;
637 }
wdenk7ac16102004-08-01 22:48:16 +0000638
Remy Bohmereec38a12008-06-03 15:26:25 +0200639 if (rxbyte != DM9000_PKT_RDY)
640 return 0; /* No packet received, ignore */
wdenk7ac16102004-08-01 22:48:16 +0000641
Remy Bohmereec38a12008-06-03 15:26:25 +0200642 DM9000_DBG("receiving packet\n");
643
644 /* A packet ready now & Get status/length */
645 (db->rx_status)(&RxStatus, &RxLen);
wdenk7ac16102004-08-01 22:48:16 +0000646
Remy Bohmereec38a12008-06-03 15:26:25 +0200647 DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
648
649 /* Move data from DM9000 */
650 /* Read received packet from RX SRAM */
651 (db->inblk)(rdptr, RxLen);
652
653 if ((RxStatus & 0xbf00) || (RxLen < 0x40)
654 || (RxLen > DM9000_PKT_MAX)) {
655 if (RxStatus & 0x100) {
656 printf("rx fifo error\n");
657 }
658 if (RxStatus & 0x200) {
659 printf("rx crc error\n");
660 }
661 if (RxStatus & 0x8000) {
662 printf("rx length error\n");
663 }
664 if (RxLen > DM9000_PKT_MAX) {
665 printf("rx length too big\n");
666 dm9000_reset();
667 }
668 } else {
669 DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
670
671 DM9000_DBG("passing packet to upper layer\n");
672 NetReceive(NetRxPackets[0], RxLen);
673 }
wdenk7ac16102004-08-01 22:48:16 +0000674 }
675 return 0;
676}
677
678/*
679 Read a word data from SROM
680*/
stefano babic6708a602007-08-30 23:01:49 +0200681u16
wdenk7ac16102004-08-01 22:48:16 +0000682read_srom_word(int offset)
683{
684 DM9000_iow(DM9000_EPAR, offset);
685 DM9000_iow(DM9000_EPCR, 0x4);
stefano babicedb06872007-08-21 15:50:33 +0200686 udelay(8000);
wdenk7ac16102004-08-01 22:48:16 +0000687 DM9000_iow(DM9000_EPCR, 0x0);
688 return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
689}
690
stefano babic6708a602007-08-30 23:01:49 +0200691void
692write_srom_word(int offset, u16 val)
693{
694 DM9000_iow(DM9000_EPAR, offset);
695 DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
696 DM9000_iow(DM9000_EPDRL, (val & 0xff));
697 DM9000_iow(DM9000_EPCR, 0x12);
698 udelay(8000);
699 DM9000_iow(DM9000_EPCR, 0);
700}
701
702
wdenk7ac16102004-08-01 22:48:16 +0000703/*
704 Read a byte from I/O port
705*/
706static u8
707DM9000_ior(int reg)
708{
709 DM9000_outb(reg, DM9000_IO);
710 return DM9000_inb(DM9000_DATA);
711}
712
713/*
714 Write a byte to I/O port
715*/
716static void
717DM9000_iow(int reg, u8 value)
718{
719 DM9000_outb(reg, DM9000_IO);
720 DM9000_outb(value, DM9000_DATA);
721}
722
723/*
724 Read a word from phyxcer
725*/
726static u16
727phy_read(int reg)
728{
729 u16 val;
730
731 /* Fill the phyxcer register into REG_0C */
732 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
733 DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200734 udelay(100); /* Wait read complete */
wdenk7ac16102004-08-01 22:48:16 +0000735 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
736 val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
737
738 /* The read data keeps on REG_0D & REG_0E */
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200739 DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
wdenk7ac16102004-08-01 22:48:16 +0000740 return val;
741}
742
743/*
744 Write a word to phyxcer
745*/
746static void
747phy_write(int reg, u16 value)
748{
749
750 /* Fill the phyxcer register into REG_0C */
751 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
752
753 /* Fill the written data into REG_0D & REG_0E */
754 DM9000_iow(DM9000_EPDRL, (value & 0xff));
755 DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
756 DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
Remy Bohmer61b8dbd2008-06-03 15:26:26 +0200757 udelay(500); /* Wait write complete */
wdenk7ac16102004-08-01 22:48:16 +0000758 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
Remy Bohmerf4329dc2008-06-03 15:26:22 +0200759 DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
wdenk7ac16102004-08-01 22:48:16 +0000760}