]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/net/dm9000x.c
sunxi: Fix A20-OLinuXino-MICRO LAN8710 support
[people/ms/u-boot.git] / drivers / net / dm9000x.c
CommitLineData
281e00a3
WD
1/*
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
1a459660 7 * SPDX-License-Identifier: GPL-2.0+
281e00a3
WD
8
9 (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
10
11V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match
53677ef1
WD
12 06/22/2001 Support DM9801 progrmming
13 E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
14 E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
15 R17 = (R17 & 0xfff0) | NF + 3
16 E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
17 R17 = (R17 & 0xfff0) | NF
18
19v1.00 modify by simon 2001.9.5
93e14596 20 change for kernel 2.4.x
281e00a3 21
53677ef1 22v1.1 11/09/2001 fix force mode bug
281e00a3
WD
23
24v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>:
25 Fixed phy reset.
26 Added tx/rx 32 bit mode.
27 Cleaned up for kernel merge.
28
29--------------------------------------
30
a101361b
RB
31 12/15/2003 Initial port to u-boot by
32 Sascha Hauer <saschahauer@web.de>
33
34 06/03/2008 Remy Bohmer <linux@bohmer.net>
850ba755
RB
35 - Fixed the driver to work with DM9000A.
36 (check on ISR receive status bit before reading the
37 FIFO as described in DM9000 programming guide and
38 application notes)
a101361b 39 - Added autodetect of databus width.
134e2662 40 - Made debug code compile again.
acba3184
RB
41 - Adapt eth_send such that it matches the DM9000*
42 application notes. Needed to make it work properly
43 for DM9000A.
fbcb7ece
RB
44 - Adapted reset procedure to match DM9000 application
45 notes (i.e. double reset)
98291e2e 46 - some minor code cleanups
a101361b 47 These changes are tested with DM9000{A,EP,E} together
e5a3bc24 48 with a 200MHz Atmel AT91SAM9261 core
281e00a3 49
d26b739a 50TODO: external MII is not functional, only internal at the moment.
281e00a3
WD
51*/
52
53#include <common.h>
54#include <command.h>
55#include <net.h>
56#include <asm/io.h>
e5a3bc24 57#include <dm9000.h>
281e00a3 58
281e00a3
WD
59#include "dm9000x.h"
60
61/* Board/System/Debug information/definition ---------------- */
62
281e00a3
WD
63/* #define CONFIG_DM9000_DEBUG */
64
65#ifdef CONFIG_DM9000_DEBUG
134e2662
RB
66#define DM9000_DBG(fmt,args...) printf(fmt, ##args)
67#define DM9000_DMP_PACKET(func,packet,length) \
68 do { \
69 int i; \
076cd24c 70 printf("%s: length: %d\n", func, length); \
134e2662
RB
71 for (i = 0; i < length; i++) { \
72 if (i % 8 == 0) \
73 printf("\n%s: %02x: ", func, i); \
74 printf("%02x ", ((unsigned char *) packet)[i]); \
75 } printf("\n"); \
76 } while(0)
77#else
281e00a3 78#define DM9000_DBG(fmt,args...)
134e2662
RB
79#define DM9000_DMP_PACKET(func,packet,length)
80#endif
81
281e00a3
WD
82/* Structure/enum declaration ------------------------------- */
83typedef struct board_info {
84 u32 runt_length_counter; /* counter: RX length < 64byte */
85 u32 long_length_counter; /* counter: RX length > 1514byte */
86 u32 reset_counter; /* counter: RESET */
87 u32 reset_tx_timeout; /* RESET caused by TX Timeout */
88 u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
89 u16 tx_pkt_cnt;
90 u16 queue_start_addr;
91 u16 dbug_cnt;
92 u8 phy_addr;
93 u8 device_wait_reset; /* device state */
281e00a3 94 unsigned char srom[128];
0e38c938 95 void (*outblk)(volatile void *data_ptr, int count);
a101361b
RB
96 void (*inblk)(void *data_ptr, int count);
97 void (*rx_status)(u16 *RxStatus, u16 *RxLen);
60f61e6d 98 struct eth_device netdev;
98291e2e 99} board_info_t;
a101361b 100static board_info_t dm9000_info;
281e00a3 101
60f61e6d 102
281e00a3 103/* function declaration ------------------------------------- */
281e00a3 104static int dm9000_probe(void);
09c04c20
AF
105static u16 dm9000_phy_read(int);
106static void dm9000_phy_write(int, u16);
281e00a3
WD
107static u8 DM9000_ior(int);
108static void DM9000_iow(int reg, u8 value);
109
110/* DM9000 network board routine ---------------------------- */
5c1d082b 111#ifndef CONFIG_DM9000_BYTE_SWAPPED
67bee2fb
MF
112#define DM9000_outb(d,r) writeb(d, (volatile u8 *)(r))
113#define DM9000_outw(d,r) writew(d, (volatile u16 *)(r))
114#define DM9000_outl(d,r) writel(d, (volatile u32 *)(r))
115#define DM9000_inb(r) readb((volatile u8 *)(r))
116#define DM9000_inw(r) readw((volatile u16 *)(r))
117#define DM9000_inl(r) readl((volatile u32 *)(r))
5c1d082b
JJ
118#else
119#define DM9000_outb(d, r) __raw_writeb(d, r)
120#define DM9000_outw(d, r) __raw_writew(d, r)
121#define DM9000_outl(d, r) __raw_writel(d, r)
122#define DM9000_inb(r) __raw_readb(r)
123#define DM9000_inw(r) __raw_readw(r)
124#define DM9000_inl(r) __raw_readl(r)
125#endif
281e00a3
WD
126
127#ifdef CONFIG_DM9000_DEBUG
128static void
129dump_regs(void)
130{
131 DM9000_DBG("\n");
132 DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0));
133 DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1));
134 DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2));
135 DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3));
136 DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
137 DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
138 DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
134e2662 139 DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
281e00a3
WD
140 DM9000_DBG("\n");
141}
a101361b
RB
142#endif
143
0e38c938 144static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
a101361b
RB
145{
146 int i;
147 for (i = 0; i < count; i++)
148 DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
149}
150
0e38c938 151static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
a101361b
RB
152{
153 int i;
154 u32 tmplen = (count + 1) / 2;
155
156 for (i = 0; i < tmplen; i++)
157 DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
158}
0e38c938 159static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
a101361b
RB
160{
161 int i;
162 u32 tmplen = (count + 3) / 4;
163
164 for (i = 0; i < tmplen; i++)
165 DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
166}
167
168static void dm9000_inblk_8bit(void *data_ptr, int count)
169{
170 int i;
171 for (i = 0; i < count; i++)
172 ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
173}
174
175static void dm9000_inblk_16bit(void *data_ptr, int count)
176{
177 int i;
178 u32 tmplen = (count + 1) / 2;
179
180 for (i = 0; i < tmplen; i++)
181 ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
182}
183static void dm9000_inblk_32bit(void *data_ptr, int count)
184{
185 int i;
186 u32 tmplen = (count + 3) / 4;
187
188 for (i = 0; i < tmplen; i++)
189 ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
190}
191
192static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
193{
d6ee5fa4 194 u32 tmpdata;
a101361b
RB
195
196 DM9000_outb(DM9000_MRCMD, DM9000_IO);
197
d6ee5fa4 198 tmpdata = DM9000_inl(DM9000_DATA);
943b825b
TL
199 *RxStatus = __le16_to_cpu(tmpdata);
200 *RxLen = __le16_to_cpu(tmpdata >> 16);
a101361b
RB
201}
202
203static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
204{
205 DM9000_outb(DM9000_MRCMD, DM9000_IO);
206
943b825b
TL
207 *RxStatus = __le16_to_cpu(DM9000_inw(DM9000_DATA));
208 *RxLen = __le16_to_cpu(DM9000_inw(DM9000_DATA));
a101361b
RB
209}
210
211static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
212{
213 DM9000_outb(DM9000_MRCMD, DM9000_IO);
214
943b825b
TL
215 *RxStatus =
216 __le16_to_cpu(DM9000_inb(DM9000_DATA) +
217 (DM9000_inb(DM9000_DATA) << 8));
218 *RxLen =
219 __le16_to_cpu(DM9000_inb(DM9000_DATA) +
220 (DM9000_inb(DM9000_DATA) << 8));
a101361b 221}
281e00a3
WD
222
223/*
224 Search DM9000 board, allocate space and register it
225*/
226int
227dm9000_probe(void)
228{
229 u32 id_val;
230 id_val = DM9000_ior(DM9000_VIDL);
231 id_val |= DM9000_ior(DM9000_VIDH) << 8;
232 id_val |= DM9000_ior(DM9000_PIDL) << 16;
233 id_val |= DM9000_ior(DM9000_PIDH) << 24;
234 if (id_val == DM9000_ID) {
235 printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
236 id_val);
237 return 0;
238 } else {
239 printf("dm9000 not found at 0x%08x id: 0x%08x\n",
240 CONFIG_DM9000_BASE, id_val);
241 return -1;
242 }
243}
244
281e00a3
WD
245/* General Purpose dm9000 reset routine */
246static void
247dm9000_reset(void)
248{
fbcb7ece
RB
249 DM9000_DBG("resetting DM9000\n");
250
251 /* Reset DM9000,
252 see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
253
d26b739a
AD
254 /* DEBUG: Make all GPIO0 outputs, all others inputs */
255 DM9000_iow(DM9000_GPCR, GPCR_GPIO0_OUT);
fbcb7ece
RB
256 /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
257 DM9000_iow(DM9000_GPR, 0);
258 /* Step 2: Software reset */
d26b739a 259 DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
fbcb7ece
RB
260
261 do {
262 DM9000_DBG("resetting the DM9000, 1st reset\n");
263 udelay(25); /* Wait at least 20 us */
264 } while (DM9000_ior(DM9000_NCR) & 1);
265
266 DM9000_iow(DM9000_NCR, 0);
d26b739a 267 DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); /* Issue a second reset */
fbcb7ece
RB
268
269 do {
270 DM9000_DBG("resetting the DM9000, 2nd reset\n");
271 udelay(25); /* Wait at least 20 us */
272 } while (DM9000_ior(DM9000_NCR) & 1);
273
274 /* Check whether the ethernet controller is present */
275 if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
276 (DM9000_ior(DM9000_PIDH) != 0x90))
277 printf("ERROR: resetting DM9000 -> not responding\n");
281e00a3
WD
278}
279
60f61e6d 280/* Initialize dm9000 board
281e00a3 281*/
60f61e6d 282static int dm9000_init(struct eth_device *dev, bd_t *bd)
281e00a3
WD
283{
284 int i, oft, lnk;
a101361b
RB
285 u8 io_mode;
286 struct board_info *db = &dm9000_info;
287
60f61e6d 288 DM9000_DBG("%s\n", __func__);
281e00a3
WD
289
290 /* RESET device */
291 dm9000_reset();
d26b739a
AD
292
293 if (dm9000_probe() < 0)
294 return -1;
281e00a3 295
a101361b
RB
296 /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
297 io_mode = DM9000_ior(DM9000_ISR) >> 6;
298
299 switch (io_mode) {
300 case 0x0: /* 16-bit mode */
301 printf("DM9000: running in 16 bit mode\n");
302 db->outblk = dm9000_outblk_16bit;
303 db->inblk = dm9000_inblk_16bit;
304 db->rx_status = dm9000_rx_status_16bit;
305 break;
306 case 0x01: /* 32-bit mode */
307 printf("DM9000: running in 32 bit mode\n");
308 db->outblk = dm9000_outblk_32bit;
309 db->inblk = dm9000_inblk_32bit;
310 db->rx_status = dm9000_rx_status_32bit;
311 break;
312 case 0x02: /* 8 bit mode */
313 printf("DM9000: running in 8 bit mode\n");
314 db->outblk = dm9000_outblk_8bit;
315 db->inblk = dm9000_inblk_8bit;
316 db->rx_status = dm9000_rx_status_8bit;
317 break;
318 default:
319 /* Assume 8 bit mode, will probably not work anyway */
320 printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
321 db->outblk = dm9000_outblk_8bit;
322 db->inblk = dm9000_inblk_8bit;
323 db->rx_status = dm9000_rx_status_8bit;
324 break;
325 }
326
d26b739a 327 /* Program operating register, only internal phy supported */
98291e2e
RB
328 DM9000_iow(DM9000_NCR, 0x0);
329 /* TX Polling clear */
330 DM9000_iow(DM9000_TCR, 0);
331 /* Less 3Kb, 200us */
d26b739a 332 DM9000_iow(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);
98291e2e
RB
333 /* Flow Control : High/Low Water */
334 DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
335 /* SH FIXME: This looks strange! Flow Control */
336 DM9000_iow(DM9000_FCR, 0x0);
337 /* Special Mode */
338 DM9000_iow(DM9000_SMCR, 0);
339 /* clear TX status */
340 DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
341 /* Clear interrupt status */
d26b739a 342 DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
281e00a3 343
07754372 344 printf("MAC: %pM\n", dev->enetaddr);
0adb5b76 345 if (!is_valid_ethaddr(dev->enetaddr)) {
c583ee16 346 printf("WARNING: Bad MAC address (uninitialized EEPROM?)\n");
c583ee16 347 }
d26b739a
AD
348
349 /* fill device MAC address registers */
350 for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
07754372 351 DM9000_iow(oft, dev->enetaddr[i]);
281e00a3
WD
352 for (i = 0, oft = 0x16; i < 8; i++, oft++)
353 DM9000_iow(oft, 0xff);
354
355 /* read back mac, just to be sure */
356 for (i = 0, oft = 0x10; i < 6; i++, oft++)
357 DM9000_DBG("%02x:", DM9000_ior(oft));
358 DM9000_DBG("\n");
359
360 /* Activate DM9000 */
98291e2e
RB
361 /* RX enable */
362 DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
363 /* Enable TX/RX interrupt mask */
364 DM9000_iow(DM9000_IMR, IMR_PAR);
365
281e00a3 366 i = 0;
09c04c20 367 while (!(dm9000_phy_read(1) & 0x20)) { /* autonegation complete bit */
281e00a3
WD
368 udelay(1000);
369 i++;
370 if (i == 10000) {
371 printf("could not establish link\n");
372 return 0;
373 }
374 }
375
376 /* see what we've got */
09c04c20 377 lnk = dm9000_phy_read(17) >> 12;
281e00a3
WD
378 printf("operating at ");
379 switch (lnk) {
380 case 1:
381 printf("10M half duplex ");
382 break;
383 case 2:
384 printf("10M full duplex ");
385 break;
386 case 4:
387 printf("100M half duplex ");
388 break;
389 case 8:
390 printf("100M full duplex ");
391 break;
392 default:
393 printf("unknown: %d ", lnk);
394 break;
395 }
396 printf("mode\n");
397 return 0;
398}
399
400/*
401 Hardware start transmission.
402 Send a packet to media from the upper layer.
403*/
7f9a8a67 404static int dm9000_send(struct eth_device *netdev, void *packet, int length)
281e00a3 405{
281e00a3 406 int tmo;
a101361b
RB
407 struct board_info *db = &dm9000_info;
408
60f61e6d 409 DM9000_DMP_PACKET(__func__ , packet, length);
281e00a3 410
acba3184
RB
411 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
412
281e00a3 413 /* Move data to DM9000 TX RAM */
acba3184 414 DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
281e00a3 415
a101361b 416 /* push the data to the TX-fifo */
0e38c938 417 (db->outblk)(packet, length);
281e00a3
WD
418
419 /* Set TX length to DM9000 */
420 DM9000_iow(DM9000_TXPLL, length & 0xff);
421 DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
422
423 /* Issue TX polling command */
acba3184 424 DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
281e00a3
WD
425
426 /* wait for end of transmission */
6d0f6bcf 427 tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
acba3184
RB
428 while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
429 !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
281e00a3
WD
430 if (get_timer(0) >= tmo) {
431 printf("transmission timeout\n");
432 break;
433 }
434 }
acba3184
RB
435 DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
436
281e00a3
WD
437 DM9000_DBG("transmit done\n\n");
438 return 0;
439}
440
441/*
442 Stop the interface.
443 The interface is stopped when it is brought.
444*/
60f61e6d 445static void dm9000_halt(struct eth_device *netdev)
281e00a3 446{
60f61e6d 447 DM9000_DBG("%s\n", __func__);
281e00a3
WD
448
449 /* RESET devie */
09c04c20 450 dm9000_phy_write(0, 0x8000); /* PHY RESET */
281e00a3
WD
451 DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
452 DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
453 DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
454}
455
456/*
457 Received a packet and pass to upper layer
458*/
60f61e6d 459static int dm9000_rx(struct eth_device *netdev)
281e00a3 460{
1fd92db8
JH
461 u8 rxbyte;
462 u8 *rdptr = (u8 *)net_rx_packets[0];
281e00a3 463 u16 RxStatus, RxLen = 0;
a101361b 464 struct board_info *db = &dm9000_info;
281e00a3 465
850ba755
RB
466 /* Check packet ready or not, we must check
467 the ISR status first for DM9000A */
468 if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
281e00a3
WD
469 return 0;
470
850ba755 471 DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
281e00a3 472
850ba755
RB
473 /* There is _at least_ 1 package in the fifo, read them all */
474 for (;;) {
475 DM9000_ior(DM9000_MRCMDX); /* Dummy read */
281e00a3 476
0e38c938
RB
477 /* Get most updated data,
478 only look at bits 0:1, See application notes DM9000 */
479 rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
281e00a3 480
850ba755
RB
481 /* Status check: this byte must be 0 or 1 */
482 if (rxbyte > DM9000_PKT_RDY) {
483 DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
484 DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
485 printf("DM9000 error: status check fail: 0x%x\n",
486 rxbyte);
487 return 0;
488 }
281e00a3 489
850ba755
RB
490 if (rxbyte != DM9000_PKT_RDY)
491 return 0; /* No packet received, ignore */
492
493 DM9000_DBG("receiving packet\n");
494
495 /* A packet ready now & Get status/length */
496 (db->rx_status)(&RxStatus, &RxLen);
497
498 DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
499
500 /* Move data from DM9000 */
501 /* Read received packet from RX SRAM */
502 (db->inblk)(rdptr, RxLen);
503
504 if ((RxStatus & 0xbf00) || (RxLen < 0x40)
505 || (RxLen > DM9000_PKT_MAX)) {
506 if (RxStatus & 0x100) {
507 printf("rx fifo error\n");
508 }
509 if (RxStatus & 0x200) {
510 printf("rx crc error\n");
511 }
512 if (RxStatus & 0x8000) {
513 printf("rx length error\n");
514 }
515 if (RxLen > DM9000_PKT_MAX) {
516 printf("rx length too big\n");
517 dm9000_reset();
518 }
519 } else {
60f61e6d 520 DM9000_DMP_PACKET(__func__ , rdptr, RxLen);
281e00a3 521
850ba755 522 DM9000_DBG("passing packet to upper layer\n");
1fd92db8 523 net_process_received_packet(net_rx_packets[0], RxLen);
281e00a3 524 }
281e00a3
WD
525 }
526 return 0;
527}
528
529/*
530 Read a word data from SROM
531*/
e5a3bc24
RB
532#if !defined(CONFIG_DM9000_NO_SROM)
533void dm9000_read_srom_word(int offset, u8 *to)
281e00a3
WD
534{
535 DM9000_iow(DM9000_EPAR, offset);
536 DM9000_iow(DM9000_EPCR, 0x4);
5f470948 537 udelay(8000);
281e00a3 538 DM9000_iow(DM9000_EPCR, 0x0);
ad74cae9
DB
539 to[0] = DM9000_ior(DM9000_EPDRL);
540 to[1] = DM9000_ior(DM9000_EPDRH);
281e00a3
WD
541}
542
e5a3bc24 543void dm9000_write_srom_word(int offset, u16 val)
5e5803e1
SB
544{
545 DM9000_iow(DM9000_EPAR, offset);
546 DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
547 DM9000_iow(DM9000_EPDRL, (val & 0xff));
548 DM9000_iow(DM9000_EPCR, 0x12);
549 udelay(8000);
550 DM9000_iow(DM9000_EPCR, 0);
551}
e5a3bc24 552#endif
5e5803e1 553
07754372
BW
554static void dm9000_get_enetaddr(struct eth_device *dev)
555{
556#if !defined(CONFIG_DM9000_NO_SROM)
557 int i;
558 for (i = 0; i < 3; i++)
559 dm9000_read_srom_word(i, dev->enetaddr + (2 * i));
560#endif
561}
562
281e00a3
WD
563/*
564 Read a byte from I/O port
565*/
566static u8
567DM9000_ior(int reg)
568{
569 DM9000_outb(reg, DM9000_IO);
570 return DM9000_inb(DM9000_DATA);
571}
572
573/*
574 Write a byte to I/O port
575*/
576static void
577DM9000_iow(int reg, u8 value)
578{
579 DM9000_outb(reg, DM9000_IO);
580 DM9000_outb(value, DM9000_DATA);
581}
582
583/*
584 Read a word from phyxcer
585*/
586static u16
09c04c20 587dm9000_phy_read(int reg)
281e00a3
WD
588{
589 u16 val;
590
591 /* Fill the phyxcer register into REG_0C */
592 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
593 DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
98291e2e 594 udelay(100); /* Wait read complete */
281e00a3
WD
595 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
596 val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
597
598 /* The read data keeps on REG_0D & REG_0E */
09c04c20 599 DM9000_DBG("dm9000_phy_read(0x%x): 0x%x\n", reg, val);
281e00a3
WD
600 return val;
601}
602
603/*
604 Write a word to phyxcer
605*/
606static void
09c04c20 607dm9000_phy_write(int reg, u16 value)
281e00a3
WD
608{
609
610 /* Fill the phyxcer register into REG_0C */
611 DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
612
613 /* Fill the written data into REG_0D & REG_0E */
614 DM9000_iow(DM9000_EPDRL, (value & 0xff));
615 DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
616 DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
98291e2e 617 udelay(500); /* Wait write complete */
281e00a3 618 DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
09c04c20 619 DM9000_DBG("dm9000_phy_write(reg:0x%x, value:0x%x)\n", reg, value);
281e00a3 620}
60f61e6d
RB
621
622int dm9000_initialize(bd_t *bis)
623{
624 struct eth_device *dev = &(dm9000_info.netdev);
625
07754372
BW
626 /* Load MAC address from EEPROM */
627 dm9000_get_enetaddr(dev);
628
60f61e6d
RB
629 dev->init = dm9000_init;
630 dev->halt = dm9000_halt;
631 dev->send = dm9000_send;
632 dev->recv = dm9000_rx;
192bc694 633 strcpy(dev->name, "dm9000");
60f61e6d
RB
634
635 eth_register(dev);
636
637 return 0;
638}