xref: /openbmc/u-boot/drivers/net/dm9000x.c (revision e5a3bc24)
12439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
22439e4bfSJean-Christophe PLAGNIOL-VILLARD   dm9000.c: Version 1.2 12/15/2003
32439e4bfSJean-Christophe PLAGNIOL-VILLARD 
42439e4bfSJean-Christophe PLAGNIOL-VILLARD 	A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
52439e4bfSJean-Christophe PLAGNIOL-VILLARD 	Copyright (C) 1997  Sten Wang
62439e4bfSJean-Christophe PLAGNIOL-VILLARD 
72439e4bfSJean-Christophe PLAGNIOL-VILLARD 	This program is free software; you can redistribute it and/or
82439e4bfSJean-Christophe PLAGNIOL-VILLARD 	modify it under the terms of the GNU General Public License
92439e4bfSJean-Christophe PLAGNIOL-VILLARD 	as published by the Free Software Foundation; either version 2
102439e4bfSJean-Christophe PLAGNIOL-VILLARD 	of the License, or (at your option) any later version.
112439e4bfSJean-Christophe PLAGNIOL-VILLARD 
122439e4bfSJean-Christophe PLAGNIOL-VILLARD 	This program is distributed in the hope that it will be useful,
132439e4bfSJean-Christophe PLAGNIOL-VILLARD 	but WITHOUT ANY WARRANTY; without even the implied warranty of
142439e4bfSJean-Christophe PLAGNIOL-VILLARD 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
152439e4bfSJean-Christophe PLAGNIOL-VILLARD 	GNU General Public License for more details.
162439e4bfSJean-Christophe PLAGNIOL-VILLARD 
172439e4bfSJean-Christophe PLAGNIOL-VILLARD   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
182439e4bfSJean-Christophe PLAGNIOL-VILLARD 
192439e4bfSJean-Christophe PLAGNIOL-VILLARD V0.11	06/20/2001	REG_0A bit3=1, default enable BP with DA match
202439e4bfSJean-Christophe PLAGNIOL-VILLARD 	06/22/2001	Support DM9801 progrmming
212439e4bfSJean-Christophe PLAGNIOL-VILLARD 			E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
222439e4bfSJean-Christophe PLAGNIOL-VILLARD 			E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
232439e4bfSJean-Christophe PLAGNIOL-VILLARD 		R17 = (R17 & 0xfff0) | NF + 3
242439e4bfSJean-Christophe PLAGNIOL-VILLARD 			E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
252439e4bfSJean-Christophe PLAGNIOL-VILLARD 		R17 = (R17 & 0xfff0) | NF
262439e4bfSJean-Christophe PLAGNIOL-VILLARD 
272439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.00			modify by simon 2001.9.5
282439e4bfSJean-Christophe PLAGNIOL-VILLARD 	                change for kernel 2.4.x
292439e4bfSJean-Christophe PLAGNIOL-VILLARD 
302439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.1   11/09/2001	fix force mode bug
312439e4bfSJean-Christophe PLAGNIOL-VILLARD 
322439e4bfSJean-Christophe PLAGNIOL-VILLARD v1.2   03/18/2003       Weilun Huang <weilun_huang@davicom.com.tw>:
332439e4bfSJean-Christophe PLAGNIOL-VILLARD 			Fixed phy reset.
342439e4bfSJean-Christophe PLAGNIOL-VILLARD 			Added tx/rx 32 bit mode.
352439e4bfSJean-Christophe PLAGNIOL-VILLARD 			Cleaned up for kernel merge.
362439e4bfSJean-Christophe PLAGNIOL-VILLARD 
372439e4bfSJean-Christophe PLAGNIOL-VILLARD --------------------------------------
382439e4bfSJean-Christophe PLAGNIOL-VILLARD 
39a101361bSRemy Bohmer        12/15/2003       Initial port to u-boot by
40a101361bSRemy Bohmer        			Sascha Hauer <saschahauer@web.de>
41a101361bSRemy Bohmer 
42a101361bSRemy Bohmer        06/03/2008	Remy Bohmer <linux@bohmer.net>
43850ba755SRemy Bohmer 			- Fixed the driver to work with DM9000A.
44850ba755SRemy Bohmer 			  (check on ISR receive status bit before reading the
45850ba755SRemy Bohmer 			  FIFO as described in DM9000 programming guide and
46850ba755SRemy Bohmer 			  application notes)
47a101361bSRemy Bohmer 			- Added autodetect of databus width.
48134e2662SRemy Bohmer 			- Made debug code compile again.
49acba3184SRemy Bohmer 			- Adapt eth_send such that it matches the DM9000*
50acba3184SRemy Bohmer 			  application notes. Needed to make it work properly
51acba3184SRemy Bohmer 			  for DM9000A.
52fbcb7eceSRemy Bohmer 			- Adapted reset procedure to match DM9000 application
53fbcb7eceSRemy Bohmer 			  notes (i.e. double reset)
5498291e2eSRemy Bohmer 			- some minor code cleanups
55a101361bSRemy Bohmer 			These changes are tested with DM9000{A,EP,E} together
56*e5a3bc24SRemy Bohmer 			with a 200MHz Atmel AT91SAM9261 core
572439e4bfSJean-Christophe PLAGNIOL-VILLARD 
58d26b739aSAndrew Dyer TODO: external MII is not functional, only internal at the moment.
592439e4bfSJean-Christophe PLAGNIOL-VILLARD */
602439e4bfSJean-Christophe PLAGNIOL-VILLARD 
612439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
622439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <command.h>
632439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <net.h>
642439e4bfSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h>
65*e5a3bc24SRemy Bohmer #include <dm9000.h>
662439e4bfSJean-Christophe PLAGNIOL-VILLARD 
672439e4bfSJean-Christophe PLAGNIOL-VILLARD #include "dm9000x.h"
682439e4bfSJean-Christophe PLAGNIOL-VILLARD 
692439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Board/System/Debug information/definition ---------------- */
702439e4bfSJean-Christophe PLAGNIOL-VILLARD 
712439e4bfSJean-Christophe PLAGNIOL-VILLARD /* #define CONFIG_DM9000_DEBUG */
722439e4bfSJean-Christophe PLAGNIOL-VILLARD 
732439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DM9000_DEBUG
742439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_DBG(fmt,args...) printf(fmt, ##args)
75134e2662SRemy Bohmer #define DM9000_DMP_PACKET(func,packet,length)  \
76134e2662SRemy Bohmer 	do { \
77134e2662SRemy Bohmer 		int i; 							\
78134e2662SRemy Bohmer 		printf(func ": length: %d\n", length);			\
79134e2662SRemy Bohmer 		for (i = 0; i < length; i++) {				\
80134e2662SRemy Bohmer 			if (i % 8 == 0)					\
81134e2662SRemy Bohmer 				printf("\n%s: %02x: ", func, i);	\
82134e2662SRemy Bohmer 			printf("%02x ", ((unsigned char *) packet)[i]);	\
83134e2662SRemy Bohmer 		} printf("\n");						\
84134e2662SRemy Bohmer 	} while(0)
85134e2662SRemy Bohmer #else
862439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_DBG(fmt,args...)
87134e2662SRemy Bohmer #define DM9000_DMP_PACKET(func,packet,length)
88134e2662SRemy Bohmer #endif
89134e2662SRemy Bohmer 
902439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Structure/enum declaration ------------------------------- */
912439e4bfSJean-Christophe PLAGNIOL-VILLARD typedef struct board_info {
922439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 runt_length_counter;	/* counter: RX length < 64byte */
932439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 long_length_counter;	/* counter: RX length > 1514byte */
942439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 reset_counter;	/* counter: RESET */
952439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 reset_tx_timeout;	/* RESET caused by TX Timeout */
962439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 reset_rx_status;	/* RESET caused by RX Statsus wrong */
972439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u16 tx_pkt_cnt;
982439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u16 queue_start_addr;
992439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u16 dbug_cnt;
1002439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u8 phy_addr;
1012439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u8 device_wait_reset;	/* device state */
1022439e4bfSJean-Christophe PLAGNIOL-VILLARD 	unsigned char srom[128];
1030e38c938SRemy Bohmer 	void (*outblk)(volatile void *data_ptr, int count);
104a101361bSRemy Bohmer 	void (*inblk)(void *data_ptr, int count);
105a101361bSRemy Bohmer 	void (*rx_status)(u16 *RxStatus, u16 *RxLen);
1062439e4bfSJean-Christophe PLAGNIOL-VILLARD } board_info_t;
107a101361bSRemy Bohmer static board_info_t dm9000_info;
1082439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1092439e4bfSJean-Christophe PLAGNIOL-VILLARD /* function declaration ------------------------------------- */
1102439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_init(bd_t * bd);
1112439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_send(volatile void *, int);
1122439e4bfSJean-Christophe PLAGNIOL-VILLARD int eth_rx(void);
1132439e4bfSJean-Christophe PLAGNIOL-VILLARD void eth_halt(void);
1142439e4bfSJean-Christophe PLAGNIOL-VILLARD static int dm9000_probe(void);
1152439e4bfSJean-Christophe PLAGNIOL-VILLARD static u16 phy_read(int);
1162439e4bfSJean-Christophe PLAGNIOL-VILLARD static void phy_write(int, u16);
1172439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8 DM9000_ior(int);
1182439e4bfSJean-Christophe PLAGNIOL-VILLARD static void DM9000_iow(int reg, u8 value);
1192439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1202439e4bfSJean-Christophe PLAGNIOL-VILLARD /* DM9000 network board routine ---------------------------- */
1212439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1222439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outb(d,r) ( *(volatile u8 *)r = d )
1232439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outw(d,r) ( *(volatile u16 *)r = d )
1242439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_outl(d,r) ( *(volatile u32 *)r = d )
1252439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inb(r) (*(volatile u8 *)r)
1262439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inw(r) (*(volatile u16 *)r)
1272439e4bfSJean-Christophe PLAGNIOL-VILLARD #define DM9000_inl(r) (*(volatile u32 *)r)
1282439e4bfSJean-Christophe PLAGNIOL-VILLARD 
1292439e4bfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_DM9000_DEBUG
1302439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
1312439e4bfSJean-Christophe PLAGNIOL-VILLARD dump_regs(void)
1322439e4bfSJean-Christophe PLAGNIOL-VILLARD {
1332439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("\n");
1342439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("NCR   (0x00): %02x\n", DM9000_ior(0));
1352439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("NSR   (0x01): %02x\n", DM9000_ior(1));
1362439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("TCR   (0x02): %02x\n", DM9000_ior(2));
1372439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("TSRI  (0x03): %02x\n", DM9000_ior(3));
1382439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4));
1392439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("RCR   (0x05): %02x\n", DM9000_ior(5));
1402439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("RSR   (0x06): %02x\n", DM9000_ior(6));
141134e2662SRemy Bohmer 	DM9000_DBG("ISR   (0xFE): %02x\n", DM9000_ior(DM9000_ISR));
1422439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("\n");
1432439e4bfSJean-Christophe PLAGNIOL-VILLARD }
144a101361bSRemy Bohmer #endif
145a101361bSRemy Bohmer 
1460e38c938SRemy Bohmer static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
147a101361bSRemy Bohmer {
148a101361bSRemy Bohmer 	int i;
149a101361bSRemy Bohmer 	for (i = 0; i < count; i++)
150a101361bSRemy Bohmer 		DM9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
151a101361bSRemy Bohmer }
152a101361bSRemy Bohmer 
1530e38c938SRemy Bohmer static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
154a101361bSRemy Bohmer {
155a101361bSRemy Bohmer 	int i;
156a101361bSRemy Bohmer 	u32 tmplen = (count + 1) / 2;
157a101361bSRemy Bohmer 
158a101361bSRemy Bohmer 	for (i = 0; i < tmplen; i++)
159a101361bSRemy Bohmer 		DM9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
160a101361bSRemy Bohmer }
1610e38c938SRemy Bohmer static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
162a101361bSRemy Bohmer {
163a101361bSRemy Bohmer 	int i;
164a101361bSRemy Bohmer 	u32 tmplen = (count + 3) / 4;
165a101361bSRemy Bohmer 
166a101361bSRemy Bohmer 	for (i = 0; i < tmplen; i++)
167a101361bSRemy Bohmer 		DM9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
168a101361bSRemy Bohmer }
169a101361bSRemy Bohmer 
170a101361bSRemy Bohmer static void dm9000_inblk_8bit(void *data_ptr, int count)
171a101361bSRemy Bohmer {
172a101361bSRemy Bohmer 	int i;
173a101361bSRemy Bohmer 	for (i = 0; i < count; i++)
174a101361bSRemy Bohmer 		((u8 *) data_ptr)[i] = DM9000_inb(DM9000_DATA);
175a101361bSRemy Bohmer }
176a101361bSRemy Bohmer 
177a101361bSRemy Bohmer static void dm9000_inblk_16bit(void *data_ptr, int count)
178a101361bSRemy Bohmer {
179a101361bSRemy Bohmer 	int i;
180a101361bSRemy Bohmer 	u32 tmplen = (count + 1) / 2;
181a101361bSRemy Bohmer 
182a101361bSRemy Bohmer 	for (i = 0; i < tmplen; i++)
183a101361bSRemy Bohmer 		((u16 *) data_ptr)[i] = DM9000_inw(DM9000_DATA);
184a101361bSRemy Bohmer }
185a101361bSRemy Bohmer static void dm9000_inblk_32bit(void *data_ptr, int count)
186a101361bSRemy Bohmer {
187a101361bSRemy Bohmer 	int i;
188a101361bSRemy Bohmer 	u32 tmplen = (count + 3) / 4;
189a101361bSRemy Bohmer 
190a101361bSRemy Bohmer 	for (i = 0; i < tmplen; i++)
191a101361bSRemy Bohmer 		((u32 *) data_ptr)[i] = DM9000_inl(DM9000_DATA);
192a101361bSRemy Bohmer }
193a101361bSRemy Bohmer 
194a101361bSRemy Bohmer static void dm9000_rx_status_32bit(u16 *RxStatus, u16 *RxLen)
195a101361bSRemy Bohmer {
196d6ee5fa4SRemy Bohmer 	u32 tmpdata;
197a101361bSRemy Bohmer 
198a101361bSRemy Bohmer 	DM9000_outb(DM9000_MRCMD, DM9000_IO);
199a101361bSRemy Bohmer 
200d6ee5fa4SRemy Bohmer 	tmpdata = DM9000_inl(DM9000_DATA);
201943b825bSTsiChung Liew 	*RxStatus = __le16_to_cpu(tmpdata);
202943b825bSTsiChung Liew 	*RxLen = __le16_to_cpu(tmpdata >> 16);
203a101361bSRemy Bohmer }
204a101361bSRemy Bohmer 
205a101361bSRemy Bohmer static void dm9000_rx_status_16bit(u16 *RxStatus, u16 *RxLen)
206a101361bSRemy Bohmer {
207a101361bSRemy Bohmer 	DM9000_outb(DM9000_MRCMD, DM9000_IO);
208a101361bSRemy Bohmer 
209943b825bSTsiChung Liew 	*RxStatus = __le16_to_cpu(DM9000_inw(DM9000_DATA));
210943b825bSTsiChung Liew 	*RxLen = __le16_to_cpu(DM9000_inw(DM9000_DATA));
211a101361bSRemy Bohmer }
212a101361bSRemy Bohmer 
213a101361bSRemy Bohmer static void dm9000_rx_status_8bit(u16 *RxStatus, u16 *RxLen)
214a101361bSRemy Bohmer {
215a101361bSRemy Bohmer 	DM9000_outb(DM9000_MRCMD, DM9000_IO);
216a101361bSRemy Bohmer 
217943b825bSTsiChung Liew 	*RxStatus =
218943b825bSTsiChung Liew 	    __le16_to_cpu(DM9000_inb(DM9000_DATA) +
219943b825bSTsiChung Liew 			  (DM9000_inb(DM9000_DATA) << 8));
220943b825bSTsiChung Liew 	*RxLen =
221943b825bSTsiChung Liew 	    __le16_to_cpu(DM9000_inb(DM9000_DATA) +
222943b825bSTsiChung Liew 			  (DM9000_inb(DM9000_DATA) << 8));
223a101361bSRemy Bohmer }
2242439e4bfSJean-Christophe PLAGNIOL-VILLARD 
2252439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
2262439e4bfSJean-Christophe PLAGNIOL-VILLARD   Search DM9000 board, allocate space and register it
2272439e4bfSJean-Christophe PLAGNIOL-VILLARD */
2282439e4bfSJean-Christophe PLAGNIOL-VILLARD int
2292439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_probe(void)
2302439e4bfSJean-Christophe PLAGNIOL-VILLARD {
2312439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u32 id_val;
2322439e4bfSJean-Christophe PLAGNIOL-VILLARD 	id_val = DM9000_ior(DM9000_VIDL);
2332439e4bfSJean-Christophe PLAGNIOL-VILLARD 	id_val |= DM9000_ior(DM9000_VIDH) << 8;
2342439e4bfSJean-Christophe PLAGNIOL-VILLARD 	id_val |= DM9000_ior(DM9000_PIDL) << 16;
2352439e4bfSJean-Christophe PLAGNIOL-VILLARD 	id_val |= DM9000_ior(DM9000_PIDH) << 24;
2362439e4bfSJean-Christophe PLAGNIOL-VILLARD 	if (id_val == DM9000_ID) {
2372439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
2382439e4bfSJean-Christophe PLAGNIOL-VILLARD 		       id_val);
2392439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
2402439e4bfSJean-Christophe PLAGNIOL-VILLARD 	} else {
2412439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("dm9000 not found at 0x%08x id: 0x%08x\n",
2422439e4bfSJean-Christophe PLAGNIOL-VILLARD 		       CONFIG_DM9000_BASE, id_val);
2432439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return -1;
2442439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
2452439e4bfSJean-Christophe PLAGNIOL-VILLARD }
2462439e4bfSJean-Christophe PLAGNIOL-VILLARD 
2472439e4bfSJean-Christophe PLAGNIOL-VILLARD /* General Purpose dm9000 reset routine */
2482439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
2492439e4bfSJean-Christophe PLAGNIOL-VILLARD dm9000_reset(void)
2502439e4bfSJean-Christophe PLAGNIOL-VILLARD {
251fbcb7eceSRemy Bohmer 	DM9000_DBG("resetting DM9000\n");
252fbcb7eceSRemy Bohmer 
253fbcb7eceSRemy Bohmer 	/* Reset DM9000,
254fbcb7eceSRemy Bohmer 	   see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
255fbcb7eceSRemy Bohmer 
256d26b739aSAndrew Dyer 	/* DEBUG: Make all GPIO0 outputs, all others inputs */
257d26b739aSAndrew Dyer 	DM9000_iow(DM9000_GPCR, GPCR_GPIO0_OUT);
258fbcb7eceSRemy Bohmer 	/* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
259fbcb7eceSRemy Bohmer 	DM9000_iow(DM9000_GPR, 0);
260fbcb7eceSRemy Bohmer 	/* Step 2: Software reset */
261d26b739aSAndrew Dyer 	DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
262fbcb7eceSRemy Bohmer 
263fbcb7eceSRemy Bohmer 	do {
264fbcb7eceSRemy Bohmer 		DM9000_DBG("resetting the DM9000, 1st reset\n");
265fbcb7eceSRemy Bohmer 		udelay(25); /* Wait at least 20 us */
266fbcb7eceSRemy Bohmer 	} while (DM9000_ior(DM9000_NCR) & 1);
267fbcb7eceSRemy Bohmer 
268fbcb7eceSRemy Bohmer 	DM9000_iow(DM9000_NCR, 0);
269d26b739aSAndrew Dyer 	DM9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); /* Issue a second reset */
270fbcb7eceSRemy Bohmer 
271fbcb7eceSRemy Bohmer 	do {
272fbcb7eceSRemy Bohmer 		DM9000_DBG("resetting the DM9000, 2nd reset\n");
273fbcb7eceSRemy Bohmer 		udelay(25); /* Wait at least 20 us */
274fbcb7eceSRemy Bohmer 	} while (DM9000_ior(DM9000_NCR) & 1);
275fbcb7eceSRemy Bohmer 
276fbcb7eceSRemy Bohmer 	/* Check whether the ethernet controller is present */
277fbcb7eceSRemy Bohmer 	if ((DM9000_ior(DM9000_PIDL) != 0x0) ||
278fbcb7eceSRemy Bohmer 	    (DM9000_ior(DM9000_PIDH) != 0x90))
279fbcb7eceSRemy Bohmer 		printf("ERROR: resetting DM9000 -> not responding\n");
2802439e4bfSJean-Christophe PLAGNIOL-VILLARD }
2812439e4bfSJean-Christophe PLAGNIOL-VILLARD 
2822439e4bfSJean-Christophe PLAGNIOL-VILLARD /* Initilize dm9000 board
2832439e4bfSJean-Christophe PLAGNIOL-VILLARD */
2842439e4bfSJean-Christophe PLAGNIOL-VILLARD int
2852439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_init(bd_t * bd)
2862439e4bfSJean-Christophe PLAGNIOL-VILLARD {
2872439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int i, oft, lnk;
288a101361bSRemy Bohmer 	u8 io_mode;
289a101361bSRemy Bohmer 	struct board_info *db = &dm9000_info;
290d3f87148SMike Frysinger 	uchar enetaddr[6];
291a101361bSRemy Bohmer 
2922439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("eth_init()\n");
2932439e4bfSJean-Christophe PLAGNIOL-VILLARD 
2942439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* RESET device */
2952439e4bfSJean-Christophe PLAGNIOL-VILLARD 	dm9000_reset();
296d26b739aSAndrew Dyer 
297d26b739aSAndrew Dyer 	if (dm9000_probe() < 0)
298d26b739aSAndrew Dyer 		return -1;
2992439e4bfSJean-Christophe PLAGNIOL-VILLARD 
300a101361bSRemy Bohmer 	/* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
301a101361bSRemy Bohmer 	io_mode = DM9000_ior(DM9000_ISR) >> 6;
302a101361bSRemy Bohmer 
303a101361bSRemy Bohmer 	switch (io_mode) {
304a101361bSRemy Bohmer 	case 0x0:  /* 16-bit mode */
305a101361bSRemy Bohmer 		printf("DM9000: running in 16 bit mode\n");
306a101361bSRemy Bohmer 		db->outblk    = dm9000_outblk_16bit;
307a101361bSRemy Bohmer 		db->inblk     = dm9000_inblk_16bit;
308a101361bSRemy Bohmer 		db->rx_status = dm9000_rx_status_16bit;
309a101361bSRemy Bohmer 		break;
310a101361bSRemy Bohmer 	case 0x01:  /* 32-bit mode */
311a101361bSRemy Bohmer 		printf("DM9000: running in 32 bit mode\n");
312a101361bSRemy Bohmer 		db->outblk    = dm9000_outblk_32bit;
313a101361bSRemy Bohmer 		db->inblk     = dm9000_inblk_32bit;
314a101361bSRemy Bohmer 		db->rx_status = dm9000_rx_status_32bit;
315a101361bSRemy Bohmer 		break;
316a101361bSRemy Bohmer 	case 0x02: /* 8 bit mode */
317a101361bSRemy Bohmer 		printf("DM9000: running in 8 bit mode\n");
318a101361bSRemy Bohmer 		db->outblk    = dm9000_outblk_8bit;
319a101361bSRemy Bohmer 		db->inblk     = dm9000_inblk_8bit;
320a101361bSRemy Bohmer 		db->rx_status = dm9000_rx_status_8bit;
321a101361bSRemy Bohmer 		break;
322a101361bSRemy Bohmer 	default:
323a101361bSRemy Bohmer 		/* Assume 8 bit mode, will probably not work anyway */
324a101361bSRemy Bohmer 		printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
325a101361bSRemy Bohmer 		db->outblk    = dm9000_outblk_8bit;
326a101361bSRemy Bohmer 		db->inblk     = dm9000_inblk_8bit;
327a101361bSRemy Bohmer 		db->rx_status = dm9000_rx_status_8bit;
328a101361bSRemy Bohmer 		break;
329a101361bSRemy Bohmer 	}
330a101361bSRemy Bohmer 
331d26b739aSAndrew Dyer 	/* Program operating register, only internal phy supported */
33298291e2eSRemy Bohmer 	DM9000_iow(DM9000_NCR, 0x0);
33398291e2eSRemy Bohmer 	/* TX Polling clear */
33498291e2eSRemy Bohmer 	DM9000_iow(DM9000_TCR, 0);
33598291e2eSRemy Bohmer 	/* Less 3Kb, 200us */
336d26b739aSAndrew Dyer 	DM9000_iow(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);
33798291e2eSRemy Bohmer 	/* Flow Control : High/Low Water */
33898291e2eSRemy Bohmer 	DM9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
33998291e2eSRemy Bohmer 	/* SH FIXME: This looks strange! Flow Control */
34098291e2eSRemy Bohmer 	DM9000_iow(DM9000_FCR, 0x0);
34198291e2eSRemy Bohmer 	/* Special Mode */
34298291e2eSRemy Bohmer 	DM9000_iow(DM9000_SMCR, 0);
34398291e2eSRemy Bohmer 	/* clear TX status */
34498291e2eSRemy Bohmer 	DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
34598291e2eSRemy Bohmer 	/* Clear interrupt status */
346d26b739aSAndrew Dyer 	DM9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
3472439e4bfSJean-Christophe PLAGNIOL-VILLARD 
3482439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Set Node address */
349d3f87148SMike Frysinger 	if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
350*e5a3bc24SRemy Bohmer #if !defined(CONFIG_DM9000_NO_SROM)
351ad74cae9SDavid Brownell 		for (i = 0; i < 3; i++)
352*e5a3bc24SRemy Bohmer 			dm9000_read_srom_word(i, enetaddr + 2 * i);
353d3f87148SMike Frysinger 		eth_setenv_enetaddr("ethaddr", enetaddr);
354d99a8ff6SStelian Pop #endif
3552439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
3562439e4bfSJean-Christophe PLAGNIOL-VILLARD 
357d3f87148SMike Frysinger 	printf("MAC: %pM\n", enetaddr);
358d26b739aSAndrew Dyer 
359d26b739aSAndrew Dyer 	/* fill device MAC address registers */
360d26b739aSAndrew Dyer 	for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
361d3f87148SMike Frysinger 		DM9000_iow(oft, enetaddr[i]);
3622439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0, oft = 0x16; i < 8; i++, oft++)
3632439e4bfSJean-Christophe PLAGNIOL-VILLARD 		DM9000_iow(oft, 0xff);
3642439e4bfSJean-Christophe PLAGNIOL-VILLARD 
3652439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* read back mac, just to be sure */
3662439e4bfSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0, oft = 0x10; i < 6; i++, oft++)
3672439e4bfSJean-Christophe PLAGNIOL-VILLARD 		DM9000_DBG("%02x:", DM9000_ior(oft));
3682439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("\n");
3692439e4bfSJean-Christophe PLAGNIOL-VILLARD 
3702439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Activate DM9000 */
37198291e2eSRemy Bohmer 	/* RX enable */
37298291e2eSRemy Bohmer 	DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
37398291e2eSRemy Bohmer 	/* Enable TX/RX interrupt mask */
37498291e2eSRemy Bohmer 	DM9000_iow(DM9000_IMR, IMR_PAR);
37598291e2eSRemy Bohmer 
3762439e4bfSJean-Christophe PLAGNIOL-VILLARD 	i = 0;
3772439e4bfSJean-Christophe PLAGNIOL-VILLARD 	while (!(phy_read(1) & 0x20)) {	/* autonegation complete bit */
3782439e4bfSJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
3792439e4bfSJean-Christophe PLAGNIOL-VILLARD 		i++;
3802439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (i == 10000) {
3812439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("could not establish link\n");
3822439e4bfSJean-Christophe PLAGNIOL-VILLARD 			return 0;
3832439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
3842439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
3852439e4bfSJean-Christophe PLAGNIOL-VILLARD 
3862439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* see what we've got */
3872439e4bfSJean-Christophe PLAGNIOL-VILLARD 	lnk = phy_read(17) >> 12;
3882439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf("operating at ");
3892439e4bfSJean-Christophe PLAGNIOL-VILLARD 	switch (lnk) {
3902439e4bfSJean-Christophe PLAGNIOL-VILLARD 	case 1:
3912439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("10M half duplex ");
3922439e4bfSJean-Christophe PLAGNIOL-VILLARD 		break;
3932439e4bfSJean-Christophe PLAGNIOL-VILLARD 	case 2:
3942439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("10M full duplex ");
3952439e4bfSJean-Christophe PLAGNIOL-VILLARD 		break;
3962439e4bfSJean-Christophe PLAGNIOL-VILLARD 	case 4:
3972439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("100M half duplex ");
3982439e4bfSJean-Christophe PLAGNIOL-VILLARD 		break;
3992439e4bfSJean-Christophe PLAGNIOL-VILLARD 	case 8:
4002439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("100M full duplex ");
4012439e4bfSJean-Christophe PLAGNIOL-VILLARD 		break;
4022439e4bfSJean-Christophe PLAGNIOL-VILLARD 	default:
4032439e4bfSJean-Christophe PLAGNIOL-VILLARD 		printf("unknown: %d ", lnk);
4042439e4bfSJean-Christophe PLAGNIOL-VILLARD 		break;
4052439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
4062439e4bfSJean-Christophe PLAGNIOL-VILLARD 	printf("mode\n");
4072439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
4082439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4092439e4bfSJean-Christophe PLAGNIOL-VILLARD 
4102439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4112439e4bfSJean-Christophe PLAGNIOL-VILLARD   Hardware start transmission.
4122439e4bfSJean-Christophe PLAGNIOL-VILLARD   Send a packet to media from the upper layer.
4132439e4bfSJean-Christophe PLAGNIOL-VILLARD */
4142439e4bfSJean-Christophe PLAGNIOL-VILLARD int
4152439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_send(volatile void *packet, int length)
4162439e4bfSJean-Christophe PLAGNIOL-VILLARD {
4172439e4bfSJean-Christophe PLAGNIOL-VILLARD 	int tmo;
418a101361bSRemy Bohmer 	struct board_info *db = &dm9000_info;
419a101361bSRemy Bohmer 
420134e2662SRemy Bohmer 	DM9000_DMP_PACKET("eth_send", packet, length);
4212439e4bfSJean-Christophe PLAGNIOL-VILLARD 
422acba3184SRemy Bohmer 	DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
423acba3184SRemy Bohmer 
4242439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Move data to DM9000 TX RAM */
425acba3184SRemy Bohmer 	DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
4262439e4bfSJean-Christophe PLAGNIOL-VILLARD 
427a101361bSRemy Bohmer 	/* push the data to the TX-fifo */
4280e38c938SRemy Bohmer 	(db->outblk)(packet, length);
4292439e4bfSJean-Christophe PLAGNIOL-VILLARD 
4302439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Set TX length to DM9000 */
4312439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_TXPLL, length & 0xff);
4322439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
4332439e4bfSJean-Christophe PLAGNIOL-VILLARD 
4342439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Issue TX polling command */
4352439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
4362439e4bfSJean-Christophe PLAGNIOL-VILLARD 
4372439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* wait for end of transmission */
4386d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
439acba3184SRemy Bohmer 	while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
440acba3184SRemy Bohmer 		!(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
4412439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if (get_timer(0) >= tmo) {
4422439e4bfSJean-Christophe PLAGNIOL-VILLARD 			printf("transmission timeout\n");
4432439e4bfSJean-Christophe PLAGNIOL-VILLARD 			break;
4442439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
4452439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
446acba3184SRemy Bohmer 	DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
447acba3184SRemy Bohmer 
4482439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("transmit done\n\n");
4492439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
4502439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4512439e4bfSJean-Christophe PLAGNIOL-VILLARD 
4522439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4532439e4bfSJean-Christophe PLAGNIOL-VILLARD   Stop the interface.
4542439e4bfSJean-Christophe PLAGNIOL-VILLARD   The interface is stopped when it is brought.
4552439e4bfSJean-Christophe PLAGNIOL-VILLARD */
4562439e4bfSJean-Christophe PLAGNIOL-VILLARD void
4572439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_halt(void)
4582439e4bfSJean-Christophe PLAGNIOL-VILLARD {
4592439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_DBG("eth_halt\n");
4602439e4bfSJean-Christophe PLAGNIOL-VILLARD 
4612439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* RESET devie */
4622439e4bfSJean-Christophe PLAGNIOL-VILLARD 	phy_write(0, 0x8000);	/* PHY RESET */
4632439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_GPR, 0x01);	/* Power-Down PHY */
4642439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_IMR, 0x80);	/* Disable all interrupt */
4652439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_RCR, 0x00);	/* Disable RX */
4662439e4bfSJean-Christophe PLAGNIOL-VILLARD }
4672439e4bfSJean-Christophe PLAGNIOL-VILLARD 
4682439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
4692439e4bfSJean-Christophe PLAGNIOL-VILLARD   Received a packet and pass to upper layer
4702439e4bfSJean-Christophe PLAGNIOL-VILLARD */
4712439e4bfSJean-Christophe PLAGNIOL-VILLARD int
4722439e4bfSJean-Christophe PLAGNIOL-VILLARD eth_rx(void)
4732439e4bfSJean-Christophe PLAGNIOL-VILLARD {
4742439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
4752439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u16 RxStatus, RxLen = 0;
476a101361bSRemy Bohmer 	struct board_info *db = &dm9000_info;
4772439e4bfSJean-Christophe PLAGNIOL-VILLARD 
478850ba755SRemy Bohmer 	/* Check packet ready or not, we must check
479850ba755SRemy Bohmer 	   the ISR status first for DM9000A */
480850ba755SRemy Bohmer 	if (!(DM9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
4812439e4bfSJean-Christophe PLAGNIOL-VILLARD 		return 0;
4822439e4bfSJean-Christophe PLAGNIOL-VILLARD 
483850ba755SRemy Bohmer 	DM9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
484850ba755SRemy Bohmer 
485850ba755SRemy Bohmer 	/* There is _at least_ 1 package in the fifo, read them all */
486850ba755SRemy Bohmer 	for (;;) {
487850ba755SRemy Bohmer 		DM9000_ior(DM9000_MRCMDX);	/* Dummy read */
488850ba755SRemy Bohmer 
4890e38c938SRemy Bohmer 		/* Get most updated data,
4900e38c938SRemy Bohmer 		   only look at bits 0:1, See application notes DM9000 */
4910e38c938SRemy Bohmer 		rxbyte = DM9000_inb(DM9000_DATA) & 0x03;
492850ba755SRemy Bohmer 
4932439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Status check: this byte must be 0 or 1 */
494850ba755SRemy Bohmer 		if (rxbyte > DM9000_PKT_RDY) {
4952439e4bfSJean-Christophe PLAGNIOL-VILLARD 			DM9000_iow(DM9000_RCR, 0x00);	/* Stop Device */
4962439e4bfSJean-Christophe PLAGNIOL-VILLARD 			DM9000_iow(DM9000_ISR, 0x80);	/* Stop INT request */
497850ba755SRemy Bohmer 			printf("DM9000 error: status check fail: 0x%x\n",
498850ba755SRemy Bohmer 				rxbyte);
499850ba755SRemy Bohmer 			return 0;
5002439e4bfSJean-Christophe PLAGNIOL-VILLARD 		}
501850ba755SRemy Bohmer 
502850ba755SRemy Bohmer 		if (rxbyte != DM9000_PKT_RDY)
503850ba755SRemy Bohmer 			return 0; /* No packet received, ignore */
504850ba755SRemy Bohmer 
5052439e4bfSJean-Christophe PLAGNIOL-VILLARD 		DM9000_DBG("receiving packet\n");
5062439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5072439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* A packet ready now  & Get status/length */
508a101361bSRemy Bohmer 		(db->rx_status)(&RxStatus, &RxLen);
5092439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5102439e4bfSJean-Christophe PLAGNIOL-VILLARD 		DM9000_DBG("rx status: 0x%04x rx len: %d\n", RxStatus, RxLen);
5112439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5122439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Move data from DM9000 */
5132439e4bfSJean-Christophe PLAGNIOL-VILLARD 		/* Read received packet from RX SRAM */
514a101361bSRemy Bohmer 		(db->inblk)(rdptr, RxLen);
5152439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5162439e4bfSJean-Christophe PLAGNIOL-VILLARD 		if ((RxStatus & 0xbf00) || (RxLen < 0x40)
5172439e4bfSJean-Christophe PLAGNIOL-VILLARD 			|| (RxLen > DM9000_PKT_MAX)) {
5182439e4bfSJean-Christophe PLAGNIOL-VILLARD 			if (RxStatus & 0x100) {
5192439e4bfSJean-Christophe PLAGNIOL-VILLARD 				printf("rx fifo error\n");
5202439e4bfSJean-Christophe PLAGNIOL-VILLARD 			}
5212439e4bfSJean-Christophe PLAGNIOL-VILLARD 			if (RxStatus & 0x200) {
5222439e4bfSJean-Christophe PLAGNIOL-VILLARD 				printf("rx crc error\n");
5232439e4bfSJean-Christophe PLAGNIOL-VILLARD 			}
5242439e4bfSJean-Christophe PLAGNIOL-VILLARD 			if (RxStatus & 0x8000) {
5252439e4bfSJean-Christophe PLAGNIOL-VILLARD 				printf("rx length error\n");
5262439e4bfSJean-Christophe PLAGNIOL-VILLARD 			}
5272439e4bfSJean-Christophe PLAGNIOL-VILLARD 			if (RxLen > DM9000_PKT_MAX) {
5282439e4bfSJean-Christophe PLAGNIOL-VILLARD 				printf("rx length too big\n");
5292439e4bfSJean-Christophe PLAGNIOL-VILLARD 				dm9000_reset();
5302439e4bfSJean-Christophe PLAGNIOL-VILLARD 			}
5312439e4bfSJean-Christophe PLAGNIOL-VILLARD 		} else {
532134e2662SRemy Bohmer 			DM9000_DMP_PACKET("eth_rx", rdptr, RxLen);
5332439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5342439e4bfSJean-Christophe PLAGNIOL-VILLARD 			DM9000_DBG("passing packet to upper layer\n");
5352439e4bfSJean-Christophe PLAGNIOL-VILLARD 			NetReceive(NetRxPackets[0], RxLen);
536850ba755SRemy Bohmer 		}
5372439e4bfSJean-Christophe PLAGNIOL-VILLARD 	}
5382439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return 0;
5392439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5402439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5412439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5422439e4bfSJean-Christophe PLAGNIOL-VILLARD   Read a word data from SROM
5432439e4bfSJean-Christophe PLAGNIOL-VILLARD */
544*e5a3bc24SRemy Bohmer #if !defined(CONFIG_DM9000_NO_SROM)
545*e5a3bc24SRemy Bohmer void dm9000_read_srom_word(int offset, u8 *to)
5462439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5472439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPAR, offset);
5482439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPCR, 0x4);
5492439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay(8000);
5502439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPCR, 0x0);
551ad74cae9SDavid Brownell 	to[0] = DM9000_ior(DM9000_EPDRL);
552ad74cae9SDavid Brownell 	to[1] = DM9000_ior(DM9000_EPDRH);
5532439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5542439e4bfSJean-Christophe PLAGNIOL-VILLARD 
555*e5a3bc24SRemy Bohmer void dm9000_write_srom_word(int offset, u16 val)
5562439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5572439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPAR, offset);
5582439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
5592439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPDRL, (val & 0xff));
5602439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPCR, 0x12);
5612439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay(8000);
5622439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPCR, 0);
5632439e4bfSJean-Christophe PLAGNIOL-VILLARD }
564*e5a3bc24SRemy Bohmer #endif
5652439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5662439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5672439e4bfSJean-Christophe PLAGNIOL-VILLARD    Read a byte from I/O port
5682439e4bfSJean-Christophe PLAGNIOL-VILLARD */
5692439e4bfSJean-Christophe PLAGNIOL-VILLARD static u8
5702439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_ior(int reg)
5712439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5722439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_outb(reg, DM9000_IO);
5732439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return DM9000_inb(DM9000_DATA);
5742439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5752439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5762439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5772439e4bfSJean-Christophe PLAGNIOL-VILLARD    Write a byte to I/O port
5782439e4bfSJean-Christophe PLAGNIOL-VILLARD */
5792439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
5802439e4bfSJean-Christophe PLAGNIOL-VILLARD DM9000_iow(int reg, u8 value)
5812439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5822439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_outb(reg, DM9000_IO);
5832439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_outb(value, DM9000_DATA);
5842439e4bfSJean-Christophe PLAGNIOL-VILLARD }
5852439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5862439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
5872439e4bfSJean-Christophe PLAGNIOL-VILLARD    Read a word from phyxcer
5882439e4bfSJean-Christophe PLAGNIOL-VILLARD */
5892439e4bfSJean-Christophe PLAGNIOL-VILLARD static u16
5902439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_read(int reg)
5912439e4bfSJean-Christophe PLAGNIOL-VILLARD {
5922439e4bfSJean-Christophe PLAGNIOL-VILLARD 	u16 val;
5932439e4bfSJean-Christophe PLAGNIOL-VILLARD 
5942439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Fill the phyxcer register into REG_0C */
5952439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
5962439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPCR, 0xc);	/* Issue phyxcer read command */
5972439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay(100);			/* Wait read complete */
5982439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
5992439e4bfSJean-Christophe PLAGNIOL-VILLARD 	val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
6002439e4bfSJean-Christophe PLAGNIOL-VILLARD 
6012439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* The read data keeps on REG_0D & REG_0E */
602134e2662SRemy Bohmer 	DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
6032439e4bfSJean-Christophe PLAGNIOL-VILLARD 	return val;
6042439e4bfSJean-Christophe PLAGNIOL-VILLARD }
6052439e4bfSJean-Christophe PLAGNIOL-VILLARD 
6062439e4bfSJean-Christophe PLAGNIOL-VILLARD /*
6072439e4bfSJean-Christophe PLAGNIOL-VILLARD    Write a word to phyxcer
6082439e4bfSJean-Christophe PLAGNIOL-VILLARD */
6092439e4bfSJean-Christophe PLAGNIOL-VILLARD static void
6102439e4bfSJean-Christophe PLAGNIOL-VILLARD phy_write(int reg, u16 value)
6112439e4bfSJean-Christophe PLAGNIOL-VILLARD {
6122439e4bfSJean-Christophe PLAGNIOL-VILLARD 
6132439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Fill the phyxcer register into REG_0C */
6142439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
6152439e4bfSJean-Christophe PLAGNIOL-VILLARD 
6162439e4bfSJean-Christophe PLAGNIOL-VILLARD 	/* Fill the written data into REG_0D & REG_0E */
6172439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPDRL, (value & 0xff));
6182439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
6192439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPCR, 0xa);	/* Issue phyxcer write command */
6202439e4bfSJean-Christophe PLAGNIOL-VILLARD 	udelay(500);			/* Wait write complete */
6212439e4bfSJean-Christophe PLAGNIOL-VILLARD 	DM9000_iow(DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
622134e2662SRemy Bohmer 	DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
6232439e4bfSJean-Christophe PLAGNIOL-VILLARD }
624