1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
22439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
32439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000.c: Version 1.2 12/15/2003
42439e4bfSJean-Christophe PLAGNIOL-VILLARD
52439e4bfSJean-Christophe PLAGNIOL-VILLARD A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
62439e4bfSJean-Christophe PLAGNIOL-VILLARD Copyright (C) 1997 Sten Wang
72439e4bfSJean-Christophe PLAGNIOL-VILLARD
82439e4bfSJean-Christophe PLAGNIOL-VILLARD (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
92439e4bfSJean-Christophe PLAGNIOL-VILLARD
102439e4bfSJean-Christophe PLAGNIOL-VILLARD V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match
112439e4bfSJean-Christophe PLAGNIOL-VILLARD 06/22/2001 Support DM9801 progrmming
122439e4bfSJean-Christophe PLAGNIOL-VILLARD E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
132439e4bfSJean-Christophe PLAGNIOL-VILLARD E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
142439e4bfSJean-Christophe PLAGNIOL-VILLARD R17 = (R17 & 0xfff0) | NF + 3
152439e4bfSJean-Christophe PLAGNIOL-VILLARD E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
162439e4bfSJean-Christophe PLAGNIOL-VILLARD R17 = (R17 & 0xfff0) | NF
172439e4bfSJean-Christophe PLAGNIOL-VILLARD
182439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.00 modify by simon 2001.9.5
192439e4bfSJean-Christophe PLAGNIOL-VILLARD change for kernel 2.4.x
202439e4bfSJean-Christophe PLAGNIOL-VILLARD
212439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.1 11/09/2001 fix force mode bug
222439e4bfSJean-Christophe PLAGNIOL-VILLARD
232439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>:
242439e4bfSJean-Christophe PLAGNIOL-VILLARD Fixed phy reset.
252439e4bfSJean-Christophe PLAGNIOL-VILLARD Added tx/rx 32 bit mode.
262439e4bfSJean-Christophe PLAGNIOL-VILLARD Cleaned up for kernel merge.
272439e4bfSJean-Christophe PLAGNIOL-VILLARD
282439e4bfSJean-Christophe PLAGNIOL-VILLARD --------------------------------------
292439e4bfSJean-Christophe PLAGNIOL-VILLARD
30a101361bSRemy Bohmer 12/15/2003 Initial port to u-boot by
31a101361bSRemy Bohmer Sascha Hauer <saschahauer@web.de>
32a101361bSRemy Bohmer
33a101361bSRemy Bohmer 06/03/2008 Remy Bohmer <linux@bohmer.net>
34850ba755SRemy Bohmer - Fixed the driver to work with DM9000A.
35850ba755SRemy Bohmer (check on ISR receive status bit before reading the
36850ba755SRemy Bohmer FIFO as described in DM9000 programming guide and
37850ba755SRemy Bohmer application notes)
38a101361bSRemy Bohmer - Added autodetect of databus width.
39134e2662SRemy Bohmer - Made debug code compile again.
40acba3184SRemy Bohmer - Adapt eth_send such that it matches the DM9000*
41acba3184SRemy Bohmer application notes. Needed to make it work properly
42acba3184SRemy Bohmer for DM9000A.
43fbcb7eceSRemy Bohmer - Adapted reset procedure to match DM9000 application
44fbcb7eceSRemy Bohmer notes (i.e. double reset)
4598291e2eSRemy Bohmer - some minor code cleanups
46a101361bSRemy Bohmer These changes are tested with DM9000{A,EP,E} together
47e5a3bc24SRemy Bohmer with a 200MHz Atmel AT91SAM9261 core
482439e4bfSJean-Christophe PLAGNIOL-VILLARD
49d26b739aSAndrew Dyer TODO: external MII is not functional, only internal at the moment.
502439e4bfSJean-Christophe PLAGNIOL-VILLARD */
512439e4bfSJean-Christophe PLAGNIOL-VILLARD
522439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
532439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h>
542439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h>
552439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h>
56e5a3bc24SRemy Bohmer #include <dm9000.h>
572439e4bfSJean-Christophe PLAGNIOL-VILLARD
582439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "dm9000x.h"
592439e4bfSJean-Christophe PLAGNIOL-VILLARD
602439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Board/System/Debug information/definition ---------------- */
612439e4bfSJean-Christophe PLAGNIOL-VILLARD
622439e4bfSJean-Christophe PLAGNIOL-VILLARD /* #define CONFIG_DM9000_DEBUG */
632439e4bfSJean-Christophe PLAGNIOL-VILLARD
642439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DM9000_DEBUG
652439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_DBG(fmt,args...) printf(fmt, ##args)
66134e2662SRemy Bohmer #define DM9000_DMP_PACKET(func,packet,length) \
67134e2662SRemy Bohmer do { \
68134e2662SRemy Bohmer int i; \
69076cd24cSThomas Weber printf("%s: length: %d\n", func, length); \
70134e2662SRemy Bohmer for (i = 0; i < length; i++) { \
71134e2662SRemy Bohmer if (i % 8 == 0) \
72134e2662SRemy Bohmer printf("\n%s: %02x: ", func, i); \
73134e2662SRemy Bohmer printf("%02x ", ((unsigned char *) packet)[i]); \
74134e2662SRemy Bohmer } printf("\n"); \
75134e2662SRemy Bohmer } while(0)
76134e2662SRemy Bohmer #else
772439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_DBG(fmt,args...)
78134e2662SRemy Bohmer #define DM9000_DMP_PACKET(func,packet,length)
79134e2662SRemy Bohmer #endif
80134e2662SRemy Bohmer
812439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Structure/enum declaration ------------------------------- */
822439e4bfSJean-Christophe PLAGNIOL-VILLARD typedef struct board_info {
832439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 runt_length_counter; /* counter: RX length < 64byte */
842439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 long_length_counter; /* counter: RX length > 1514byte */
852439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_counter; /* counter: RESET */
862439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_tx_timeout; /* RESET caused by TX Timeout */
872439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
882439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 tx_pkt_cnt;
892439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 queue_start_addr;
902439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 dbug_cnt;
912439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 phy_addr;
922439e4bfSJean-Christophe PLAGNIOL-VILLARD u8 device_wait_reset; /* device state */
932439e4bfSJean-Christophe PLAGNIOL-VILLARD unsigned char srom[128];
940e38c938SRemy Bohmer void (*outblk)(volatile void *data_ptr, int count);
95a101361bSRemy Bohmer void (*inblk)(void *data_ptr, int count);
96a101361bSRemy Bohmer void (*rx_status)(u16 *RxStatus, u16 *RxLen);
9760f61e6dSRemy Bohmer struct eth_device netdev;
982439e4bfSJean-Christophe PLAGNIOL-VILLARD } board_info_t;
99a101361bSRemy Bohmer static board_info_t dm9000_info;
1002439e4bfSJean-Christophe PLAGNIOL-VILLARD
10160f61e6dSRemy Bohmer
1022439e4bfSJean-Christophe PLAGNIOL-VILLARD /* function declaration ------------------------------------- */
1032439e4bfSJean-Christophe PLAGNIOL-VILLARD static int dm9000_probe(void);
10409c04c20SAndy Fleming static u16 dm9000_phy_read(int);
10509c04c20SAndy Fleming static void dm9000_phy_write(int, u16);
1062439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8 DM9000_ior(int);
1072439e4bfSJean-Christophe PLAGNIOL-VILLARD static void DM9000_iow(int reg, u8 value);
1082439e4bfSJean-Christophe PLAGNIOL-VILLARD
1092439e4bfSJean-Christophe PLAGNIOL-VILLARD /* DM9000 network board routine ---------------------------- */
1105c1d082bSJason Jin #ifndef CONFIG_DM9000_BYTE_SWAPPED
11167bee2fbSMike Frysinger #define DM9000_outb(d,r) writeb(d, (volatile u8 *)(r))
11267bee2fbSMike Frysinger #define DM9000_outw(d,r) writew(d, (volatile u16 *)(r))
11367bee2fbSMike Frysinger #define DM9000_outl(d,r) writel(d, (volatile u32 *)(r))
11467bee2fbSMike Frysinger #define DM9000_inb(r) readb((volatile u8 *)(r))
11567bee2fbSMike Frysinger #define DM9000_inw(r) readw((volatile u16 *)(r))
11667bee2fbSMike Frysinger #define DM9000_inl(r) readl((volatile u32 *)(r))
1175c1d082bSJason Jin #else
1185c1d082bSJason Jin #define DM9000_outb(d, r) __raw_writeb(d, r)
1195c1d082bSJason Jin #define DM9000_outw(d, r) __raw_writew(d, r)
1205c1d082bSJason Jin #define DM9000_outl(d, r) __raw_writel(d, r)
1215c1d082bSJason Jin #define DM9000_inb(r) __raw_readb(r)
1225c1d082bSJason Jin #define DM9000_inw(r) __raw_readw(r)
1235c1d082bSJason Jin #define DM9000_inl(r) __raw_readl(r)
1245c1d082bSJason Jin #endif
1252439e4bfSJean-Christophe PLAGNIOL-VILLARD
1262439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DM9000_DEBUG
1272439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
dump_regs(void)1282439e4bfSJean-Christophe PLAGNIOL-VILLARD dump_regs(void)
1292439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1302439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n");
1312439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0));
1322439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1));
1332439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2));
1342439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3));
1352439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
1362439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5));
1372439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6));
138134e2662SRemy Bohmer DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
1392439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n");
1402439e4bfSJean-Christophe PLAGNIOL-VILLARD }
141a101361bSRemy Bohmer #endif
142a101361bSRemy Bohmer
dm9000_outblk_8bit(volatile void * data_ptr,int count)1430e38c938SRemy Bohmer static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
144a101361bSRemy Bohmer {
145a101361bSRemy Bohmer int i;
146a101361bSRemy Bohmer for (i = 0; i < count; i++)
147a101361bSRemy Bohmer DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
148a101361bSRemy Bohmer }
149a101361bSRemy Bohmer
dm9000_outblk_16bit(volatile void * data_ptr,int count)1500e38c938SRemy Bohmer static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
151a101361bSRemy Bohmer {
152a101361bSRemy Bohmer int i;
153a101361bSRemy Bohmer u32 tmplen = (count + 1) / 2;
154a101361bSRemy Bohmer
155a101361bSRemy Bohmer for (i = 0; i < tmplen; i++)
156a101361bSRemy Bohmer DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
157a101361bSRemy Bohmer }
dm9000_outblk_32bit(volatile void * data_ptr,int count)1580e38c938SRemy Bohmer static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
159a101361bSRemy Bohmer {
160a101361bSRemy Bohmer int i;
161a101361bSRemy Bohmer u32 tmplen = (count + 3) / 4;
162a101361bSRemy Bohmer
163a101361bSRemy Bohmer for (i = 0; i < tmplen; i++)
164a101361bSRemy Bohmer DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
165a101361bSRemy Bohmer }
166a101361bSRemy Bohmer
dm9000_inblk_8bit(void * data_ptr,int count)167a101361bSRemy Bohmer static void dm9000_inblk_8bit(void *data_ptr, int count)
168a101361bSRemy Bohmer {
169a101361bSRemy Bohmer int i;
170a101361bSRemy Bohmer for (i = 0; i < count; i++)
171a101361bSRemy Bohmer ((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
172a101361bSRemy Bohmer }
173a101361bSRemy Bohmer
dm9000_inblk_16bit(void * data_ptr,int count)174a101361bSRemy Bohmer static void dm9000_inblk_16bit(void *data_ptr, int count)
175a101361bSRemy Bohmer {
176a101361bSRemy Bohmer int i;
177a101361bSRemy Bohmer u32 tmplen = (count + 1) / 2;
178a101361bSRemy Bohmer
179a101361bSRemy Bohmer for (i = 0; i < tmplen; i++)
180a101361bSRemy Bohmer ((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
181a101361bSRemy Bohmer }
dm9000_inblk_32bit(void * data_ptr,int count)182a101361bSRemy Bohmer static void dm9000_inblk_32bit(void *data_ptr, int count)
183a101361bSRemy Bohmer {
184a101361bSRemy Bohmer int i;
185a101361bSRemy Bohmer u32 tmplen = (count + 3) / 4;
186a101361bSRemy Bohmer
187a101361bSRemy Bohmer for (i = 0; i < tmplen; i++)
188a101361bSRemy Bohmer ((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
189a101361bSRemy Bohmer }
190a101361bSRemy Bohmer
dm9000_rx_status_32bit(u16 * RxStatus,u16 * RxLen)191a101361bSRemy Bohmer static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
192a101361bSRemy Bohmer {
193d6ee5fa4SRemy Bohmer u32 tmpdata;
194a101361bSRemy Bohmer
195a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO);
196a101361bSRemy Bohmer
197d6ee5fa4SRemy Bohmer tmpdata = DM9000_inl(DM9000_DATA);
198943b825bSTsiChung Liew *RxStatus = __le16_to_cpu(tmpdata);
199943b825bSTsiChung Liew *RxLen = __le16_to_cpu(tmpdata >> 16);
200a101361bSRemy Bohmer }
201a101361bSRemy Bohmer
dm9000_rx_status_16bit(u16 * RxStatus,u16 * RxLen)202a101361bSRemy Bohmer static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
203a101361bSRemy Bohmer {
204a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO);
205a101361bSRemy Bohmer
206943b825bSTsiChung Liew *RxStatus = __le16_to_cpu(DM9000_inw(DM9000_DATA));
207943b825bSTsiChung Liew *RxLen = __le16_to_cpu(DM9000_inw(DM9000_DATA));
208a101361bSRemy Bohmer }
209a101361bSRemy Bohmer
dm9000_rx_status_8bit(u16 * RxStatus,u16 * RxLen)210a101361bSRemy Bohmer static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
211a101361bSRemy Bohmer {
212a101361bSRemy Bohmer DM9000_outb(DM9000_MRCMD, DM9000_IO);
213a101361bSRemy Bohmer
214943b825bSTsiChung Liew *RxStatus =
215943b825bSTsiChung Liew __le16_to_cpu(DM9000_inb(DM9000_DATA) +
216943b825bSTsiChung Liew (DM9000_inb(DM9000_DATA) << 8));
217943b825bSTsiChung Liew *RxLen =
218943b825bSTsiChung Liew __le16_to_cpu(DM9000_inb(DM9000_DATA) +
219943b825bSTsiChung Liew (DM9000_inb(DM9000_DATA) << 8));
220a101361bSRemy Bohmer }
2212439e4bfSJean-Christophe PLAGNIOL-VILLARD
2222439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
2232439e4bfSJean-Christophe PLAGNIOL-VILLARD Search DM9000 board, allocate space and register it
2242439e4bfSJean-Christophe PLAGNIOL-VILLARD */
2252439e4bfSJean-Christophe PLAGNIOL-VILLARD int
dm9000_probe(void)2262439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_probe(void)
2272439e4bfSJean-Christophe PLAGNIOL-VILLARD {
2282439e4bfSJean-Christophe PLAGNIOL-VILLARD u32 id_val;
2292439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val = DM9000_ior(DM9000_VIDL);
2302439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_VIDH) << 8;
2312439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_PIDL) << 16;
2322439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val |= DM9000_ior(DM9000_PIDH) << 24;
2332439e4bfSJean-Christophe PLAGNIOL-VILLARD if (id_val == DM9000_ID) {
2342439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
2352439e4bfSJean-Christophe PLAGNIOL-VILLARD id_val);
2362439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0;
2372439e4bfSJean-Christophe PLAGNIOL-VILLARD } else {
2382439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("dm9000 not found at 0x%08x id: 0x%08x\n",
2392439e4bfSJean-Christophe PLAGNIOL-VILLARD CONFIG_DM9000_BASE, id_val);
2402439e4bfSJean-Christophe PLAGNIOL-VILLARD return -1;
2412439e4bfSJean-Christophe PLAGNIOL-VILLARD }
2422439e4bfSJean-Christophe PLAGNIOL-VILLARD }
2432439e4bfSJean-Christophe PLAGNIOL-VILLARD
2442439e4bfSJean-Christophe PLAGNIOL-VILLARD /* General Purpose dm9000 reset routine */
2452439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
dm9000_reset(void)2462439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset(void)
2472439e4bfSJean-Christophe PLAGNIOL-VILLARD {
248fbcb7eceSRemy Bohmer DM9000_DBG("resetting DM9000\n");
249fbcb7eceSRemy Bohmer
250fbcb7eceSRemy Bohmer /* Reset DM9000,
251fbcb7eceSRemy Bohmer see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
252fbcb7eceSRemy Bohmer
253d26b739aSAndrew Dyer /* DEBUG: Make all GPIO0 outputs, all others inputs */
254d26b739aSAndrew Dyer DM9000_iow(DM9000_GPCR, GPCR_GPIO0_OUT);
255fbcb7eceSRemy Bohmer /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
256fbcb7eceSRemy Bohmer DM9000_iow(DM9000_GPR, 0);
257fbcb7eceSRemy Bohmer /* Step 2: Software reset */
258d26b739aSAndrew Dyer DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
259fbcb7eceSRemy Bohmer
260fbcb7eceSRemy Bohmer do {
261fbcb7eceSRemy Bohmer DM9000_DBG("resetting the DM9000, 1st reset\n");
262fbcb7eceSRemy Bohmer udelay(25); /* Wait at least 20 us */
263fbcb7eceSRemy Bohmer } while (DM9000_ior(DM9000_NCR) & 1);
264fbcb7eceSRemy Bohmer
265fbcb7eceSRemy Bohmer DM9000_iow(DM9000_NCR, 0);
266d26b739aSAndrew Dyer DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); /* Issue a second reset */
267fbcb7eceSRemy Bohmer
268fbcb7eceSRemy Bohmer do {
269fbcb7eceSRemy Bohmer DM9000_DBG("resetting the DM9000, 2nd reset\n");
270fbcb7eceSRemy Bohmer udelay(25); /* Wait at least 20 us */
271fbcb7eceSRemy Bohmer } while (DM9000_ior(DM9000_NCR) & 1);
272fbcb7eceSRemy Bohmer
273fbcb7eceSRemy Bohmer /* Check whether the ethernet controller is present */
274fbcb7eceSRemy Bohmer if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
275fbcb7eceSRemy Bohmer (DM9000_ior(DM9000_PIDH) != 0x90))
276fbcb7eceSRemy Bohmer printf("ERROR: resetting DM9000 -> not responding\n");
2772439e4bfSJean-Christophe PLAGNIOL-VILLARD }
2782439e4bfSJean-Christophe PLAGNIOL-VILLARD
27960f61e6dSRemy Bohmer /* Initialize dm9000 board
2802439e4bfSJean-Christophe PLAGNIOL-VILLARD */
dm9000_init(struct eth_device * dev,bd_t * bd)28160f61e6dSRemy Bohmer static int dm9000_init(struct eth_device *dev, bd_t *bd)
2822439e4bfSJean-Christophe PLAGNIOL-VILLARD {
2832439e4bfSJean-Christophe PLAGNIOL-VILLARD int i, oft, lnk;
284a101361bSRemy Bohmer u8 io_mode;
285a101361bSRemy Bohmer struct board_info *db = &dm9000_info;
286a101361bSRemy Bohmer
28760f61e6dSRemy Bohmer DM9000_DBG("%s\n", __func__);
2882439e4bfSJean-Christophe PLAGNIOL-VILLARD
2892439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RESET device */
2902439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset();
291d26b739aSAndrew Dyer
292d26b739aSAndrew Dyer if (dm9000_probe() < 0)
293d26b739aSAndrew Dyer return -1;
2942439e4bfSJean-Christophe PLAGNIOL-VILLARD
295a101361bSRemy Bohmer /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
296a101361bSRemy Bohmer io_mode = DM9000_ior(DM9000_ISR) >> 6;
297a101361bSRemy Bohmer
298a101361bSRemy Bohmer switch (io_mode) {
299a101361bSRemy Bohmer case 0x0: /* 16-bit mode */
300a101361bSRemy Bohmer printf("DM9000: running in 16 bit mode\n");
301a101361bSRemy Bohmer db->outblk = dm9000_outblk_16bit;
302a101361bSRemy Bohmer db->inblk = dm9000_inblk_16bit;
303a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_16bit;
304a101361bSRemy Bohmer break;
305a101361bSRemy Bohmer case 0x01: /* 32-bit mode */
306a101361bSRemy Bohmer printf("DM9000: running in 32 bit mode\n");
307a101361bSRemy Bohmer db->outblk = dm9000_outblk_32bit;
308a101361bSRemy Bohmer db->inblk = dm9000_inblk_32bit;
309a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_32bit;
310a101361bSRemy Bohmer break;
311a101361bSRemy Bohmer case 0x02: /* 8 bit mode */
312a101361bSRemy Bohmer printf("DM9000: running in 8 bit mode\n");
313a101361bSRemy Bohmer db->outblk = dm9000_outblk_8bit;
314a101361bSRemy Bohmer db->inblk = dm9000_inblk_8bit;
315a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_8bit;
316a101361bSRemy Bohmer break;
317a101361bSRemy Bohmer default:
318a101361bSRemy Bohmer /* Assume 8 bit mode, will probably not work anyway */
319a101361bSRemy Bohmer printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
320a101361bSRemy Bohmer db->outblk = dm9000_outblk_8bit;
321a101361bSRemy Bohmer db->inblk = dm9000_inblk_8bit;
322a101361bSRemy Bohmer db->rx_status = dm9000_rx_status_8bit;
323a101361bSRemy Bohmer break;
324a101361bSRemy Bohmer }
325a101361bSRemy Bohmer
326d26b739aSAndrew Dyer /* Program operating register, only internal phy supported */
32798291e2eSRemy Bohmer DM9000_iow(DM9000_NCR, 0x0);
32898291e2eSRemy Bohmer /* TX Polling clear */
32998291e2eSRemy Bohmer DM9000_iow(DM9000_TCR, 0);
33098291e2eSRemy Bohmer /* Less 3Kb, 200us */
331d26b739aSAndrew Dyer DM9000_iow(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);
33298291e2eSRemy Bohmer /* Flow Control : High/Low Water */
33398291e2eSRemy Bohmer DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
33498291e2eSRemy Bohmer /* SH FIXME: This looks strange! Flow Control */
33598291e2eSRemy Bohmer DM9000_iow(DM9000_FCR, 0x0);
33698291e2eSRemy Bohmer /* Special Mode */
33798291e2eSRemy Bohmer DM9000_iow(DM9000_SMCR, 0);
33898291e2eSRemy Bohmer /* clear TX status */
33998291e2eSRemy Bohmer DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
34098291e2eSRemy Bohmer /* Clear interrupt status */
341d26b739aSAndrew Dyer DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
3422439e4bfSJean-Christophe PLAGNIOL-VILLARD
34307754372SBen Warren printf("MAC: %pM\n", dev->enetaddr);
3440adb5b76SJoe Hershberger if (!is_valid_ethaddr(dev->enetaddr)) {
345c583ee16SAndrew Ruder printf("WARNING: Bad MAC address (uninitialized EEPROM?)\n");
346c583ee16SAndrew Ruder }
347d26b739aSAndrew Dyer
348d26b739aSAndrew Dyer /* fill device MAC address registers */
349d26b739aSAndrew Dyer for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
35007754372SBen Warren DM9000_iow(oft, dev->enetaddr[i]);
3512439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0, oft = 0x16; i < 8; i++, oft++)
3522439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(oft, 0xff);
3532439e4bfSJean-Christophe PLAGNIOL-VILLARD
3542439e4bfSJean-Christophe PLAGNIOL-VILLARD /* read back mac, just to be sure */
3552439e4bfSJean-Christophe PLAGNIOL-VILLARD for (i = 0, oft = 0x10; i < 6; i++, oft++)
3562439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("%02x:", DM9000_ior(oft));
3572439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("\n");
3582439e4bfSJean-Christophe PLAGNIOL-VILLARD
3592439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Activate DM9000 */
36098291e2eSRemy Bohmer /* RX enable */
36198291e2eSRemy Bohmer DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
36298291e2eSRemy Bohmer /* Enable TX/RX interrupt mask */
36398291e2eSRemy Bohmer DM9000_iow(DM9000_IMR, IMR_PAR);
36498291e2eSRemy Bohmer
3652439e4bfSJean-Christophe PLAGNIOL-VILLARD i = 0;
36609c04c20SAndy Fleming while (!(dm9000_phy_read(1) & 0x20)) { /* autonegation complete bit */
3672439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(1000);
3682439e4bfSJean-Christophe PLAGNIOL-VILLARD i++;
3692439e4bfSJean-Christophe PLAGNIOL-VILLARD if (i == 10000) {
3702439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("could not establish link\n");
3712439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0;
3722439e4bfSJean-Christophe PLAGNIOL-VILLARD }
3732439e4bfSJean-Christophe PLAGNIOL-VILLARD }
3742439e4bfSJean-Christophe PLAGNIOL-VILLARD
3752439e4bfSJean-Christophe PLAGNIOL-VILLARD /* see what we've got */
37609c04c20SAndy Fleming lnk = dm9000_phy_read(17) >> 12;
3772439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("operating at ");
3782439e4bfSJean-Christophe PLAGNIOL-VILLARD switch (lnk) {
3792439e4bfSJean-Christophe PLAGNIOL-VILLARD case 1:
3802439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("10M half duplex ");
3812439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
3822439e4bfSJean-Christophe PLAGNIOL-VILLARD case 2:
3832439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("10M full duplex ");
3842439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
3852439e4bfSJean-Christophe PLAGNIOL-VILLARD case 4:
3862439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("100M half duplex ");
3872439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
3882439e4bfSJean-Christophe PLAGNIOL-VILLARD case 8:
3892439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("100M full duplex ");
3902439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
3912439e4bfSJean-Christophe PLAGNIOL-VILLARD default:
3922439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("unknown: %d ", lnk);
3932439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
3942439e4bfSJean-Christophe PLAGNIOL-VILLARD }
3952439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("mode\n");
3962439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0;
3972439e4bfSJean-Christophe PLAGNIOL-VILLARD }
3982439e4bfSJean-Christophe PLAGNIOL-VILLARD
3992439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4002439e4bfSJean-Christophe PLAGNIOL-VILLARD Hardware start transmission.
4012439e4bfSJean-Christophe PLAGNIOL-VILLARD Send a packet to media from the upper layer.
4022439e4bfSJean-Christophe PLAGNIOL-VILLARD */
dm9000_send(struct eth_device * netdev,void * packet,int length)4037f9a8a67SJoe Hershberger static int dm9000_send(struct eth_device *netdev, void *packet, int length)
4042439e4bfSJean-Christophe PLAGNIOL-VILLARD {
4052439e4bfSJean-Christophe PLAGNIOL-VILLARD int tmo;
406a101361bSRemy Bohmer struct board_info *db = &dm9000_info;
407a101361bSRemy Bohmer
40860f61e6dSRemy Bohmer DM9000_DMP_PACKET(__func__ , packet, length);
4092439e4bfSJean-Christophe PLAGNIOL-VILLARD
410acba3184SRemy Bohmer DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
411acba3184SRemy Bohmer
4122439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Move data to DM9000 TX RAM */
413acba3184SRemy Bohmer DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
4142439e4bfSJean-Christophe PLAGNIOL-VILLARD
415a101361bSRemy Bohmer /* push the data to the TX-fifo */
4160e38c938SRemy Bohmer (db->outblk)(packet, length);
4172439e4bfSJean-Christophe PLAGNIOL-VILLARD
4182439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Set TX length to DM9000 */
4192439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TXPLL, length & 0xff);
4202439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
4212439e4bfSJean-Christophe PLAGNIOL-VILLARD
4222439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Issue TX polling command */
4232439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
4242439e4bfSJean-Christophe PLAGNIOL-VILLARD
4252439e4bfSJean-Christophe PLAGNIOL-VILLARD /* wait for end of transmission */
4266d0f6bcfSJean-Christophe PLAGNIOL-VILLARD tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
427acba3184SRemy Bohmer while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
428acba3184SRemy Bohmer !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
4292439e4bfSJean-Christophe PLAGNIOL-VILLARD if (get_timer(0) >= tmo) {
4302439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("transmission timeout\n");
4312439e4bfSJean-Christophe PLAGNIOL-VILLARD break;
4322439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4332439e4bfSJean-Christophe PLAGNIOL-VILLARD }
434acba3184SRemy Bohmer DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
435acba3184SRemy Bohmer
4362439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("transmit done\n\n");
4372439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0;
4382439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4392439e4bfSJean-Christophe PLAGNIOL-VILLARD
4402439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4412439e4bfSJean-Christophe PLAGNIOL-VILLARD Stop the interface.
4422439e4bfSJean-Christophe PLAGNIOL-VILLARD The interface is stopped when it is brought.
4432439e4bfSJean-Christophe PLAGNIOL-VILLARD */
dm9000_halt(struct eth_device * netdev)44460f61e6dSRemy Bohmer static void dm9000_halt(struct eth_device *netdev)
4452439e4bfSJean-Christophe PLAGNIOL-VILLARD {
44660f61e6dSRemy Bohmer DM9000_DBG("%s\n", __func__);
4472439e4bfSJean-Christophe PLAGNIOL-VILLARD
4482439e4bfSJean-Christophe PLAGNIOL-VILLARD /* RESET devie */
44909c04c20SAndy Fleming dm9000_phy_write(0, 0x8000); /* PHY RESET */
4502439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
4512439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
4522439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
4532439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4542439e4bfSJean-Christophe PLAGNIOL-VILLARD
4552439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4562439e4bfSJean-Christophe PLAGNIOL-VILLARD Received a packet and pass to upper layer
4572439e4bfSJean-Christophe PLAGNIOL-VILLARD */
dm9000_rx(struct eth_device * netdev)45860f61e6dSRemy Bohmer static int dm9000_rx(struct eth_device *netdev)
4592439e4bfSJean-Christophe PLAGNIOL-VILLARD {
4601fd92db8SJoe Hershberger u8 rxbyte;
4611fd92db8SJoe Hershberger u8 *rdptr = (u8 *)net_rx_packets[0];
4622439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 RxStatus, RxLen = 0;
463a101361bSRemy Bohmer struct board_info *db = &dm9000_info;
4642439e4bfSJean-Christophe PLAGNIOL-VILLARD
465850ba755SRemy Bohmer /* Check packet ready or not, we must check
466850ba755SRemy Bohmer the ISR status first for DM9000A */
467850ba755SRemy Bohmer if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
4682439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0;
4692439e4bfSJean-Christophe PLAGNIOL-VILLARD
470850ba755SRemy Bohmer DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
471850ba755SRemy Bohmer
472850ba755SRemy Bohmer /* There is _at least_ 1 package in the fifo, read them all */
473850ba755SRemy Bohmer for (;;) {
474850ba755SRemy Bohmer DM9000_ior(DM9000_MRCMDX); /* Dummy read */
475850ba755SRemy Bohmer
4760e38c938SRemy Bohmer /* Get most updated data,
4770e38c938SRemy Bohmer only look at bits 0:1, See application notes DM9000 */
4780e38c938SRemy Bohmer rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
479850ba755SRemy Bohmer
4802439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Status check: this byte must be 0 or 1 */
481850ba755SRemy Bohmer if (rxbyte > DM9000_PKT_RDY) {
4822439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */
4832439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
484850ba755SRemy Bohmer printf("DM9000 error: status check fail: 0x%x\n",
485850ba755SRemy Bohmer rxbyte);
486850ba755SRemy Bohmer return 0;
4872439e4bfSJean-Christophe PLAGNIOL-VILLARD }
488850ba755SRemy Bohmer
489850ba755SRemy Bohmer if (rxbyte != DM9000_PKT_RDY)
490850ba755SRemy Bohmer return 0; /* No packet received, ignore */
491850ba755SRemy Bohmer
4922439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("receiving packet\n");
4932439e4bfSJean-Christophe PLAGNIOL-VILLARD
4942439e4bfSJean-Christophe PLAGNIOL-VILLARD /* A packet ready now & Get status/length */
495a101361bSRemy Bohmer (db->rx_status)(&RxStatus, &RxLen);
4962439e4bfSJean-Christophe PLAGNIOL-VILLARD
4972439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
4982439e4bfSJean-Christophe PLAGNIOL-VILLARD
4992439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Move data from DM9000 */
5002439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Read received packet from RX SRAM */
501a101361bSRemy Bohmer (db->inblk)(rdptr, RxLen);
5022439e4bfSJean-Christophe PLAGNIOL-VILLARD
5032439e4bfSJean-Christophe PLAGNIOL-VILLARD if ((RxStatus & 0xbf00) || (RxLen < 0x40)
5042439e4bfSJean-Christophe PLAGNIOL-VILLARD || (RxLen > DM9000_PKT_MAX)) {
5052439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x100) {
5062439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx fifo error\n");
5072439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5082439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x200) {
5092439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx crc error\n");
5102439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5112439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxStatus & 0x8000) {
5122439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx length error\n");
5132439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5142439e4bfSJean-Christophe PLAGNIOL-VILLARD if (RxLen > DM9000_PKT_MAX) {
5152439e4bfSJean-Christophe PLAGNIOL-VILLARD printf("rx length too big\n");
5162439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset();
5172439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5182439e4bfSJean-Christophe PLAGNIOL-VILLARD } else {
51960f61e6dSRemy Bohmer DM9000_DMP_PACKET(__func__ , rdptr, RxLen);
5202439e4bfSJean-Christophe PLAGNIOL-VILLARD
5212439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_DBG("passing packet to upper layer\n");
5221fd92db8SJoe Hershberger net_process_received_packet(net_rx_packets[0], RxLen);
523850ba755SRemy Bohmer }
5242439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5252439e4bfSJean-Christophe PLAGNIOL-VILLARD return 0;
5262439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5272439e4bfSJean-Christophe PLAGNIOL-VILLARD
5282439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5292439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a word data from SROM
5302439e4bfSJean-Christophe PLAGNIOL-VILLARD */
531e5a3bc24SRemy Bohmer #if !defined(CONFIG_DM9000_NO_SROM)
dm9000_read_srom_word(int offset,u8 * to)532e5a3bc24SRemy Bohmer void dm9000_read_srom_word(int offset, u8 *to)
5332439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5342439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, offset);
5352439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x4);
5362439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(8000);
5372439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0);
538ad74cae9SDavid Brownell to[0] = DM9000_ior(DM9000_EPDRL);
539ad74cae9SDavid Brownell to[1] = DM9000_ior(DM9000_EPDRH);
5402439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5412439e4bfSJean-Christophe PLAGNIOL-VILLARD
dm9000_write_srom_word(int offset,u16 val)542e5a3bc24SRemy Bohmer void dm9000_write_srom_word(int offset, u16 val)
5432439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5442439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, offset);
5452439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
5462439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRL, (val & 0xff));
5472439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x12);
5482439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(8000);
5492439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0);
5502439e4bfSJean-Christophe PLAGNIOL-VILLARD }
551e5a3bc24SRemy Bohmer #endif
5522439e4bfSJean-Christophe PLAGNIOL-VILLARD
dm9000_get_enetaddr(struct eth_device * dev)55307754372SBen Warren static void dm9000_get_enetaddr(struct eth_device *dev)
55407754372SBen Warren {
55507754372SBen Warren #if !defined(CONFIG_DM9000_NO_SROM)
55607754372SBen Warren int i;
55707754372SBen Warren for (i = 0; i < 3; i++)
55807754372SBen Warren dm9000_read_srom_word(i, dev->enetaddr + (2 * i));
55907754372SBen Warren #endif
56007754372SBen Warren }
56107754372SBen Warren
5622439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5632439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a byte from I/O port
5642439e4bfSJean-Christophe PLAGNIOL-VILLARD */
5652439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8
DM9000_ior(int reg)5662439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_ior(int reg)
5672439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5682439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(reg, DM9000_IO);
5692439e4bfSJean-Christophe PLAGNIOL-VILLARD return DM9000_inb(DM9000_DATA);
5702439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5712439e4bfSJean-Christophe PLAGNIOL-VILLARD
5722439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5732439e4bfSJean-Christophe PLAGNIOL-VILLARD Write a byte to I/O port
5742439e4bfSJean-Christophe PLAGNIOL-VILLARD */
5752439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
DM9000_iow(int reg,u8 value)5762439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(int reg, u8 value)
5772439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5782439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(reg, DM9000_IO);
5792439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_outb(value, DM9000_DATA);
5802439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5812439e4bfSJean-Christophe PLAGNIOL-VILLARD
5822439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5832439e4bfSJean-Christophe PLAGNIOL-VILLARD Read a word from phyxcer
5842439e4bfSJean-Christophe PLAGNIOL-VILLARD */
5852439e4bfSJean-Christophe PLAGNIOL-VILLARD static u16
dm9000_phy_read(int reg)58609c04c20SAndy Fleming dm9000_phy_read(int reg)
5872439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5882439e4bfSJean-Christophe PLAGNIOL-VILLARD u16 val;
5892439e4bfSJean-Christophe PLAGNIOL-VILLARD
5902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the phyxcer register into REG_0C */
5912439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
5922439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
5932439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(100); /* Wait read complete */
5942439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
5952439e4bfSJean-Christophe PLAGNIOL-VILLARD val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
5962439e4bfSJean-Christophe PLAGNIOL-VILLARD
5972439e4bfSJean-Christophe PLAGNIOL-VILLARD /* The read data keeps on REG_0D & REG_0E */
59809c04c20SAndy Fleming DM9000_DBG("dm9000_phy_read(0x%x): 0x%x\n", reg, val);
5992439e4bfSJean-Christophe PLAGNIOL-VILLARD return val;
6002439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6012439e4bfSJean-Christophe PLAGNIOL-VILLARD
6022439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
6032439e4bfSJean-Christophe PLAGNIOL-VILLARD Write a word to phyxcer
6042439e4bfSJean-Christophe PLAGNIOL-VILLARD */
6052439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
dm9000_phy_write(int reg,u16 value)60609c04c20SAndy Fleming dm9000_phy_write(int reg, u16 value)
6072439e4bfSJean-Christophe PLAGNIOL-VILLARD {
6082439e4bfSJean-Christophe PLAGNIOL-VILLARD
6092439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the phyxcer register into REG_0C */
6102439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
6112439e4bfSJean-Christophe PLAGNIOL-VILLARD
6122439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Fill the written data into REG_0D & REG_0E */
6132439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRL, (value & 0xff));
6142439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
6152439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
6162439e4bfSJean-Christophe PLAGNIOL-VILLARD udelay(500); /* Wait write complete */
6172439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
61809c04c20SAndy Fleming DM9000_DBG("dm9000_phy_write(reg:0x%x, value:0x%x)\n", reg, value);
6192439e4bfSJean-Christophe PLAGNIOL-VILLARD }
62060f61e6dSRemy Bohmer
dm9000_initialize(bd_t * bis)62160f61e6dSRemy Bohmer int dm9000_initialize(bd_t *bis)
62260f61e6dSRemy Bohmer {
62360f61e6dSRemy Bohmer struct eth_device *dev = &(dm9000_info.netdev);
62460f61e6dSRemy Bohmer
62507754372SBen Warren /* Load MAC address from EEPROM */
62607754372SBen Warren dm9000_get_enetaddr(dev);
62707754372SBen Warren
62860f61e6dSRemy Bohmer dev->init = dm9000_init;
62960f61e6dSRemy Bohmer dev->halt = dm9000_halt;
63060f61e6dSRemy Bohmer dev->send = dm9000_send;
63160f61e6dSRemy Bohmer dev->recv = dm9000_rx;
632192bc694SBen Whitten strcpy(dev->name, "dm9000");
63360f61e6dSRemy Bohmer
63460f61e6dSRemy Bohmer eth_register(dev);
63560f61e6dSRemy Bohmer
63660f61e6dSRemy Bohmer return 0;
63760f61e6dSRemy Bohmer }
638