blob: 3a61b802e66c47eab510f9e881068312bc0c9cb1 [file] [log] [blame]
wdenk281e00a2004-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 Denk53677ef2008-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
wdenk281e00a2004-08-01 22:48:16 +000026
Wolfgang Denk53677ef2008-05-20 16:00:29 +020027v1.00 modify by simon 2001.9.5
wdenk281e00a2004-08-01 22:48:16 +000028 change for kernel 2.4.x
29
Wolfgang Denk53677ef2008-05-20 16:00:29 +020030v1.1 11/09/2001 fix force mode bug
wdenk281e00a2004-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 Bohmera1013612008-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 Bohmer850ba752008-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 Bohmera1013612008-06-03 15:26:21 +020047 - Added autodetect of databus width.
Remy Bohmer134e2662008-06-03 15:26:22 +020048 - Made debug code compile again.
Remy Bohmeracba3182008-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 Bohmerfbcb7ec2008-06-03 15:26:24 +020052 - Adapted reset procedure to match DM9000 application
53 notes (i.e. double reset)
Remy Bohmer98291e22008-06-03 15:26:26 +020054 - some minor code cleanups
Remy Bohmera1013612008-06-03 15:26:21 +020055 These changes are tested with DM9000{A,EP,E} together
56 with a 200MHz Atmel AT91SAM92161 core
wdenk281e00a2004-08-01 22:48:16 +000057
Andrew Dyerd26b7392008-08-26 17:03:38 -050058TODO: external MII is not functional, only internal at the moment.
wdenk281e00a2004-08-01 22:48:16 +000059*/
60
61#include <common.h>
62#include <command.h>
63#include <net.h>
64#include <asm/io.h>
65
wdenk281e00a2004-08-01 22:48:16 +000066#include "dm9000x.h"
67
68/* Board/System/Debug information/definition ---------------- */
69
wdenk281e00a2004-08-01 22:48:16 +000070/* #define CONFIG_DM9000_DEBUG */
71
72#ifdef CONFIG_DM9000_DEBUG
Remy Bohmer134e2662008-06-03 15:26:22 +020073#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
74#define DM9000_DMP_PACKET(func,packet,length) \
75 do { \
76 int i; \
77 printf(func ": length: %d\n", length); \
78 for (i = 0; i < length; i++) { \
79 if (i % 8 == 0) \
80 printf("\n%s: %02x: ", func, i); \
81 printf("%02x ", ((unsigned char *) packet)[i]); \
82 } printf("\n"); \
83 } while(0)
84#else
wdenk281e00a2004-08-01 22:48:16 +000085#define DM9000_DBG(fmt,args...)
Remy Bohmer134e2662008-06-03 15:26:22 +020086#define DM9000_DMP_PACKET(func,packet,length)
87#endif
88
wdenk281e00a2004-08-01 22:48:16 +000089/* Structure/enum declaration ------------------------------- */
90typedef struct board_info {
91 u32 runt_length_counter; /* counter: RX length < 64byte */
92 u32 long_length_counter; /* counter: RX length > 1514byte */
93 u32 reset_counter; /* counter: RESET */
94 u32 reset_tx_timeout; /* RESET caused by TX Timeout */
95 u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
96 u16 tx_pkt_cnt;
97 u16 queue_start_addr;
98 u16 dbug_cnt;
99 u8 phy_addr;
100 u8 device_wait_reset; /* device state */
wdenk281e00a2004-08-01 22:48:16 +0000101 unsigned char srom[128];
Remy Bohmer0e38c932008-06-05 13:03:36 +0200102 void (*outblk)(volatile void *data_ptr, int count);
Remy Bohmera1013612008-06-03 15:26:21 +0200103 void (*inblk)(void *data_ptr, int count);
104 void (*rx_status)(u16 *RxStatus, u16 *RxLen);
Remy Bohmer98291e22008-06-03 15:26:26 +0200105} board_info_t;
Remy Bohmera1013612008-06-03 15:26:21 +0200106static board_info_t dm9000_info;
wdenk281e00a2004-08-01 22:48:16 +0000107
wdenk281e00a2004-08-01 22:48:16 +0000108/* function declaration ------------------------------------- */
109int eth_init(bd_t * bd);
110int eth_send(volatile void *, int);
111int eth_rx(void);
112void eth_halt(void);
113static int dm9000_probe(void);
114static u16 phy_read(int);
115static void phy_write(int, u16);
stefano babic5e5803e2007-08-30 23:01:49 +0200116u16 read_srom_word(int);
wdenk281e00a2004-08-01 22:48:16 +0000117static u8 DM9000_ior(int);
118static void DM9000_iow(int reg, u8 value);
119
120/* DM9000 network board routine ---------------------------- */
121
122#define DM9000_outb(d,r) ( *(volatile u8 *)r = d )
123#define DM9000_outw(d,r) ( *(volatile u16 *)r = d )
124#define DM9000_outl(d,r) ( *(volatile u32 *)r = d )
125#define DM9000_inb(r) (*(volatile u8 *)r)
126#define DM9000_inw(r) (*(volatile u16 *)r)
127#define DM9000_inl(r) (*(volatile u32 *)r)
128
129#ifdef CONFIG_DM9000_DEBUG
130static void
131dump_regs(void)
132{
133 DM9000_DBG("\n");
134 DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0));
135 DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1));
136 DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2));
137 DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3));
138 DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
139 DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
140 DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
Remy Bohmer134e2662008-06-03 15:26:22 +0200141 DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
wdenk281e00a2004-08-01 22:48:16 +0000142 DM9000_DBG("\n");
143}
Remy Bohmera1013612008-06-03 15:26:21 +0200144#endif
145
Remy Bohmer0e38c932008-06-05 13:03:36 +0200146static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
Remy Bohmera1013612008-06-03 15:26:21 +0200147{
148 int i;
149 for (i = 0; i < count; i++)
150 DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
151}
152
Remy Bohmer0e38c932008-06-05 13:03:36 +0200153static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
Remy Bohmera1013612008-06-03 15:26:21 +0200154{
155 int i;
156 u32 tmplen = (count + 1) / 2;
157
158 for (i = 0; i < tmplen; i++)
159 DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
160}
Remy Bohmer0e38c932008-06-05 13:03:36 +0200161static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
Remy Bohmera1013612008-06-03 15:26:21 +0200162{
163 int i;
164 u32 tmplen = (count + 3) / 4;
165
166 for (i = 0; i < tmplen; i++)
167 DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
168}
169
170static void dm9000_inblk_8bit(void *data_ptr, int count)
171{
172 int i;
173 for (i = 0; i < count; i++)
174 ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
175}
176
177static void dm9000_inblk_16bit(void *data_ptr, int count)
178{
179 int i;
180 u32 tmplen = (count + 1) / 2;
181
182 for (i = 0; i < tmplen; i++)
183 ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
184}
185static void dm9000_inblk_32bit(void *data_ptr, int count)
186{
187 int i;
188 u32 tmplen = (count + 3) / 4;
189
190 for (i = 0; i < tmplen; i++)
191 ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
192}
193
194static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
195{
Remy Bohmerd6ee5fa2008-06-04 10:47:25 +0200196 u32 tmpdata;
Remy Bohmera1013612008-06-03 15:26:21 +0200197
198 DM9000_outb(DM9000_MRCMD, DM9000_IO);
199
Remy Bohmerd6ee5fa2008-06-04 10:47:25 +0200200 tmpdata = DM9000_inl(DM9000_DATA);
TsiChung Liew943b8252008-06-25 15:48:52 -0500201 *RxStatus = __le16_to_cpu(tmpdata);
202 *RxLen = __le16_to_cpu(tmpdata >> 16);
Remy Bohmera1013612008-06-03 15:26:21 +0200203}
204
205static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
206{
207 DM9000_outb(DM9000_MRCMD, DM9000_IO);
208
TsiChung Liew943b8252008-06-25 15:48:52 -0500209 *RxStatus = __le16_to_cpu(DM9000_inw(DM9000_DATA));
210 *RxLen = __le16_to_cpu(DM9000_inw(DM9000_DATA));
Remy Bohmera1013612008-06-03 15:26:21 +0200211}
212
213static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
214{
215 DM9000_outb(DM9000_MRCMD, DM9000_IO);
216
TsiChung Liew943b8252008-06-25 15:48:52 -0500217 *RxStatus =
218 __le16_to_cpu(DM9000_inb(DM9000_DATA) +
219 (DM9000_inb(DM9000_DATA) << 8));
220 *RxLen =
221 __le16_to_cpu(DM9000_inb(DM9000_DATA) +
222 (DM9000_inb(DM9000_DATA) << 8));
Remy Bohmera1013612008-06-03 15:26:21 +0200223}
wdenk281e00a2004-08-01 22:48:16 +0000224
225/*
226 Search DM9000 board, allocate space and register it
227*/
228int
229dm9000_probe(void)
230{
231 u32 id_val;
232 id_val = DM9000_ior(DM9000_VIDL);
233 id_val |= DM9000_ior(DM9000_VIDH) << 8;
234 id_val |= DM9000_ior(DM9000_PIDL) << 16;
235 id_val |= DM9000_ior(DM9000_PIDH) << 24;
236 if (id_val == DM9000_ID) {
237 printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
238 id_val);
239 return 0;
240 } else {
241 printf("dm9000 not found at 0x%08x id: 0x%08x\n",
242 CONFIG_DM9000_BASE, id_val);
243 return -1;
244 }
245}
246
wdenk281e00a2004-08-01 22:48:16 +0000247/* General Purpose dm9000 reset routine */
248static void
249dm9000_reset(void)
250{
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200251 DM9000_DBG("resetting DM9000\n");
252
253 /* Reset DM9000,
254 see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
255
Andrew Dyerd26b7392008-08-26 17:03:38 -0500256 /* DEBUG: Make all GPIO0 outputs, all others inputs */
257 DM9000_iow(DM9000_GPCR, GPCR_GPIO0_OUT);
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200258 /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
259 DM9000_iow(DM9000_GPR, 0);
260 /* Step 2: Software reset */
Andrew Dyerd26b7392008-08-26 17:03:38 -0500261 DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200262
263 do {
264 DM9000_DBG("resetting the DM9000, 1st reset\n");
265 udelay(25); /* Wait at least 20 us */
266 } while (DM9000_ior(DM9000_NCR) & 1);
267
268 DM9000_iow(DM9000_NCR, 0);
Andrew Dyerd26b7392008-08-26 17:03:38 -0500269 DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); /* Issue a second reset */
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200270
271 do {
272 DM9000_DBG("resetting the DM9000, 2nd reset\n");
273 udelay(25); /* Wait at least 20 us */
274 } while (DM9000_ior(DM9000_NCR) & 1);
275
276 /* Check whether the ethernet controller is present */
277 if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
278 (DM9000_ior(DM9000_PIDH) != 0x90))
279 printf("ERROR: resetting DM9000 -> not responding\n");
wdenk281e00a2004-08-01 22:48:16 +0000280}
281
282/* Initilize dm9000 board
283*/
284int
285eth_init(bd_t * bd)
286{
287 int i, oft, lnk;
Remy Bohmera1013612008-06-03 15:26:21 +0200288 u8 io_mode;
289 struct board_info *db = &dm9000_info;
290
wdenk281e00a2004-08-01 22:48:16 +0000291 DM9000_DBG("eth_init()\n");
292
293 /* RESET device */
294 dm9000_reset();
Andrew Dyerd26b7392008-08-26 17:03:38 -0500295
296 if (dm9000_probe() < 0)
297 return -1;
wdenk281e00a2004-08-01 22:48:16 +0000298
Remy Bohmera1013612008-06-03 15:26:21 +0200299 /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
300 io_mode = DM9000_ior(DM9000_ISR) >> 6;
301
302 switch (io_mode) {
303 case 0x0: /* 16-bit mode */
304 printf("DM9000: running in 16 bit mode\n");
305 db->outblk = dm9000_outblk_16bit;
306 db->inblk = dm9000_inblk_16bit;
307 db->rx_status = dm9000_rx_status_16bit;
308 break;
309 case 0x01: /* 32-bit mode */
310 printf("DM9000: running in 32 bit mode\n");
311 db->outblk = dm9000_outblk_32bit;
312 db->inblk = dm9000_inblk_32bit;
313 db->rx_status = dm9000_rx_status_32bit;
314 break;
315 case 0x02: /* 8 bit mode */
316 printf("DM9000: running in 8 bit mode\n");
317 db->outblk = dm9000_outblk_8bit;
318 db->inblk = dm9000_inblk_8bit;
319 db->rx_status = dm9000_rx_status_8bit;
320 break;
321 default:
322 /* Assume 8 bit mode, will probably not work anyway */
323 printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
324 db->outblk = dm9000_outblk_8bit;
325 db->inblk = dm9000_inblk_8bit;
326 db->rx_status = dm9000_rx_status_8bit;
327 break;
328 }
329
Andrew Dyerd26b7392008-08-26 17:03:38 -0500330 /* Program operating register, only internal phy supported */
Remy Bohmer98291e22008-06-03 15:26:26 +0200331 DM9000_iow(DM9000_NCR, 0x0);
332 /* TX Polling clear */
333 DM9000_iow(DM9000_TCR, 0);
334 /* Less 3Kb, 200us */
Andrew Dyerd26b7392008-08-26 17:03:38 -0500335 DM9000_iow(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);
Remy Bohmer98291e22008-06-03 15:26:26 +0200336 /* Flow Control : High/Low Water */
337 DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
338 /* SH FIXME: This looks strange! Flow Control */
339 DM9000_iow(DM9000_FCR, 0x0);
340 /* Special Mode */
341 DM9000_iow(DM9000_SMCR, 0);
342 /* clear TX status */
343 DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
344 /* Clear interrupt status */
Andrew Dyerd26b7392008-08-26 17:03:38 -0500345 DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
wdenk281e00a2004-08-01 22:48:16 +0000346
347 /* Set Node address */
Andrew Dyerd26b7392008-08-26 17:03:38 -0500348#if !defined(CONFIG_AT91SAM9261EK)
wdenk281e00a2004-08-01 22:48:16 +0000349 for (i = 0; i < 6; i++)
350 ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
Stelian Popd99a8ff2008-05-08 20:52:22 +0200351#endif
Mike Rapoport50cca8b2007-08-12 08:48:27 +0300352
stefano babic5f470942007-08-21 15:50:33 +0200353 if (is_zero_ether_addr(bd->bi_enetaddr) ||
354 is_multicast_ether_addr(bd->bi_enetaddr)) {
Mike Rapoport50cca8b2007-08-12 08:48:27 +0300355 /* try reading from environment */
356 u8 i;
357 char *s, *e;
358 s = getenv ("ethaddr");
359 for (i = 0; i < 6; ++i) {
360 bd->bi_enetaddr[i] = s ?
361 simple_strtoul (s, &e, 16) : 0;
362 if (s)
363 s = (*e) ? e + 1 : e;
364 }
365 }
366
wdenk281e00a2004-08-01 22:48:16 +0000367 printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", bd->bi_enetaddr[0],
368 bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
369 bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
Andrew Dyerd26b7392008-08-26 17:03:38 -0500370
371 /* fill device MAC address registers */
372 for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
wdenk281e00a2004-08-01 22:48:16 +0000373 DM9000_iow(oft, bd->bi_enetaddr[i]);
374 for (i = 0, oft = 0x16; i < 8; i++, oft++)
375 DM9000_iow(oft, 0xff);
376
377 /* read back mac, just to be sure */
378 for (i = 0, oft = 0x10; i < 6; i++, oft++)
379 DM9000_DBG("%02x:", DM9000_ior(oft));
380 DM9000_DBG("\n");
381
382 /* Activate DM9000 */
Remy Bohmer98291e22008-06-03 15:26:26 +0200383 /* RX enable */
384 DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
385 /* Enable TX/RX interrupt mask */
386 DM9000_iow(DM9000_IMR, IMR_PAR);
387
wdenk281e00a2004-08-01 22:48:16 +0000388 i = 0;
389 while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
390 udelay(1000);
391 i++;
392 if (i == 10000) {
393 printf("could not establish link\n");
394 return 0;
395 }
396 }
397
398 /* see what we've got */
399 lnk = phy_read(17) >> 12;
400 printf("operating at ");
401 switch (lnk) {
402 case 1:
403 printf("10M half duplex ");
404 break;
405 case 2:
406 printf("10M full duplex ");
407 break;
408 case 4:
409 printf("100M half duplex ");
410 break;
411 case 8:
412 printf("100M full duplex ");
413 break;
414 default:
415 printf("unknown: %d ", lnk);
416 break;
417 }
418 printf("mode\n");
419 return 0;
420}
421
422/*
423 Hardware start transmission.
424 Send a packet to media from the upper layer.
425*/
426int
427eth_send(volatile void *packet, int length)
428{
wdenk281e00a2004-08-01 22:48:16 +0000429 int tmo;
Remy Bohmera1013612008-06-03 15:26:21 +0200430 struct board_info *db = &dm9000_info;
431
Remy Bohmer134e2662008-06-03 15:26:22 +0200432 DM9000_DMP_PACKET("eth_send", packet, length);
wdenk281e00a2004-08-01 22:48:16 +0000433
Remy Bohmeracba3182008-06-03 15:26:23 +0200434 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
435
wdenk281e00a2004-08-01 22:48:16 +0000436 /* Move data to DM9000 TX RAM */
Remy Bohmeracba3182008-06-03 15:26:23 +0200437 DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
wdenk281e00a2004-08-01 22:48:16 +0000438
Remy Bohmera1013612008-06-03 15:26:21 +0200439 /* push the data to the TX-fifo */
Remy Bohmer0e38c932008-06-05 13:03:36 +0200440 (db->outblk)(packet, length);
wdenk281e00a2004-08-01 22:48:16 +0000441
442 /* Set TX length to DM9000 */
443 DM9000_iow(DM9000_TXPLL, length & 0xff);
444 DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
445
446 /* Issue TX polling command */
Remy Bohmeracba3182008-06-03 15:26:23 +0200447 DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
wdenk281e00a2004-08-01 22:48:16 +0000448
449 /* wait for end of transmission */
450 tmo = get_timer(0) + 5 * CFG_HZ;
Remy Bohmeracba3182008-06-03 15:26:23 +0200451 while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
452 !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
wdenk281e00a2004-08-01 22:48:16 +0000453 if (get_timer(0) >= tmo) {
454 printf("transmission timeout\n");
455 break;
456 }
457 }
Remy Bohmeracba3182008-06-03 15:26:23 +0200458 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
459
wdenk281e00a2004-08-01 22:48:16 +0000460 DM9000_DBG("transmit done\n\n");
461 return 0;
462}
463
464/*
465 Stop the interface.
466 The interface is stopped when it is brought.
467*/
468void
469eth_halt(void)
470{
471 DM9000_DBG("eth_halt\n");
472
473 /* RESET devie */
474 phy_write(0, 0x8000); /* PHY RESET */
475 DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
476 DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
477 DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
478}
479
480/*
481 Received a packet and pass to upper layer
482*/
483int
484eth_rx(void)
485{
486 u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
487 u16 RxStatus, RxLen = 0;
Remy Bohmera1013612008-06-03 15:26:21 +0200488 struct board_info *db = &dm9000_info;
wdenk281e00a2004-08-01 22:48:16 +0000489
Remy Bohmer850ba752008-06-03 15:26:25 +0200490 /* Check packet ready or not, we must check
491 the ISR status first for DM9000A */
492 if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
wdenk281e00a2004-08-01 22:48:16 +0000493 return 0;
494
Remy Bohmer850ba752008-06-03 15:26:25 +0200495 DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
wdenk281e00a2004-08-01 22:48:16 +0000496
Remy Bohmer850ba752008-06-03 15:26:25 +0200497 /* There is _at least_ 1 package in the fifo, read them all */
498 for (;;) {
499 DM9000_ior(DM9000_MRCMDX); /* Dummy read */
wdenk281e00a2004-08-01 22:48:16 +0000500
Remy Bohmer0e38c932008-06-05 13:03:36 +0200501 /* Get most updated data,
502 only look at bits 0:1, See application notes DM9000 */
503 rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
wdenk281e00a2004-08-01 22:48:16 +0000504
Remy Bohmer850ba752008-06-03 15:26:25 +0200505 /* Status check: this byte must be 0 or 1 */
506 if (rxbyte > DM9000_PKT_RDY) {
507 DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
508 DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
509 printf("DM9000 error: status check fail: 0x%x\n",
510 rxbyte);
511 return 0;
wdenk281e00a2004-08-01 22:48:16 +0000512 }
wdenk281e00a2004-08-01 22:48:16 +0000513
Remy Bohmer850ba752008-06-03 15:26:25 +0200514 if (rxbyte != DM9000_PKT_RDY)
515 return 0; /* No packet received, ignore */
516
517 DM9000_DBG("receiving packet\n");
518
519 /* A packet ready now & Get status/length */
520 (db->rx_status)(&RxStatus, &RxLen);
521
522 DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
523
524 /* Move data from DM9000 */
525 /* Read received packet from RX SRAM */
526 (db->inblk)(rdptr, RxLen);
527
528 if ((RxStatus & 0xbf00) || (RxLen < 0x40)
529 || (RxLen > DM9000_PKT_MAX)) {
530 if (RxStatus & 0x100) {
531 printf("rx fifo error\n");
532 }
533 if (RxStatus & 0x200) {
534 printf("rx crc error\n");
535 }
536 if (RxStatus & 0x8000) {
537 printf("rx length error\n");
538 }
539 if (RxLen > DM9000_PKT_MAX) {
540 printf("rx length too big\n");
541 dm9000_reset();
542 }
543 } else {
544 DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
545
546 DM9000_DBG("passing packet to upper layer\n");
547 NetReceive(NetRxPackets[0], RxLen);
548 }
wdenk281e00a2004-08-01 22:48:16 +0000549 }
550 return 0;
551}
552
553/*
554 Read a word data from SROM
555*/
stefano babic5e5803e2007-08-30 23:01:49 +0200556u16
wdenk281e00a2004-08-01 22:48:16 +0000557read_srom_word(int offset)
558{
559 DM9000_iow(DM9000_EPAR, offset);
560 DM9000_iow(DM9000_EPCR, 0x4);
stefano babic5f470942007-08-21 15:50:33 +0200561 udelay(8000);
wdenk281e00a2004-08-01 22:48:16 +0000562 DM9000_iow(DM9000_EPCR, 0x0);
563 return (DM9000_ior(DM9000_EPDRL) + (DM9000_ior(DM9000_EPDRH) << 8));
564}
565
stefano babic5e5803e2007-08-30 23:01:49 +0200566void
567write_srom_word(int offset, u16 val)
568{
569 DM9000_iow(DM9000_EPAR, offset);
570 DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
571 DM9000_iow(DM9000_EPDRL, (val & 0xff));
572 DM9000_iow(DM9000_EPCR, 0x12);
573 udelay(8000);
574 DM9000_iow(DM9000_EPCR, 0);
575}
576
577
wdenk281e00a2004-08-01 22:48:16 +0000578/*
579 Read a byte from I/O port
580*/
581static u8
582DM9000_ior(int reg)
583{
584 DM9000_outb(reg, DM9000_IO);
585 return DM9000_inb(DM9000_DATA);
586}
587
588/*
589 Write a byte to I/O port
590*/
591static void
592DM9000_iow(int reg, u8 value)
593{
594 DM9000_outb(reg, DM9000_IO);
595 DM9000_outb(value, DM9000_DATA);
596}
597
598/*
599 Read a word from phyxcer
600*/
601static u16
602phy_read(int reg)
603{
604 u16 val;
605
606 /* Fill the phyxcer register into REG_0C */
607 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
608 DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
Remy Bohmer98291e22008-06-03 15:26:26 +0200609 udelay(100); /* Wait read complete */
wdenk281e00a2004-08-01 22:48:16 +0000610 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
611 val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
612
613 /* The read data keeps on REG_0D & REG_0E */
Remy Bohmer134e2662008-06-03 15:26:22 +0200614 DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
wdenk281e00a2004-08-01 22:48:16 +0000615 return val;
616}
617
618/*
619 Write a word to phyxcer
620*/
621static void
622phy_write(int reg, u16 value)
623{
624
625 /* Fill the phyxcer register into REG_0C */
626 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
627
628 /* Fill the written data into REG_0D & REG_0E */
629 DM9000_iow(DM9000_EPDRL, (value & 0xff));
630 DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
631 DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
Remy Bohmer98291e22008-06-03 15:26:26 +0200632 udelay(500); /* Wait write complete */
wdenk281e00a2004-08-01 22:48:16 +0000633 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
Remy Bohmer134e2662008-06-03 15:26:22 +0200634 DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
wdenk281e00a2004-08-01 22:48:16 +0000635}