blob: da16b64610b888ecfc0d87129daeac307c773f22 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk281e00a2004-08-01 22:48:16 +00002/*
3 dm9000.c: Version 1.2 12/15/2003
4
5 A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
6 Copyright (C) 1997 Sten Wang
7
wdenk281e00a2004-08-01 22:48:16 +00008 (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
9
10V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match
Wolfgang Denk53677ef2008-05-20 16:00:29 +020011 06/22/2001 Support DM9801 progrmming
12 E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
13 E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
14 R17 = (R17 & 0xfff0) | NF + 3
15 E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
16 R17 = (R17 & 0xfff0) | NF
wdenk281e00a2004-08-01 22:48:16 +000017
Wolfgang Denk53677ef2008-05-20 16:00:29 +020018v1.00 modify by simon 2001.9.5
Wolfgang Denk93e14592013-10-04 17:43:24 +020019 change for kernel 2.4.x
wdenk281e00a2004-08-01 22:48:16 +000020
Wolfgang Denk53677ef2008-05-20 16:00:29 +020021v1.1 11/09/2001 fix force mode bug
wdenk281e00a2004-08-01 22:48:16 +000022
23v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>:
24 Fixed phy reset.
25 Added tx/rx 32 bit mode.
26 Cleaned up for kernel merge.
27
28--------------------------------------
29
Remy Bohmera1013612008-06-03 15:26:21 +020030 12/15/2003 Initial port to u-boot by
Wolfgang Denk0cf207e2021-09-27 17:42:39 +020031 Sascha Hauer <saschahauer@web.de>
Remy Bohmera1013612008-06-03 15:26:21 +020032
33 06/03/2008 Remy Bohmer <linux@bohmer.net>
Remy Bohmer850ba752008-06-03 15:26:25 +020034 - Fixed the driver to work with DM9000A.
35 (check on ISR receive status bit before reading the
36 FIFO as described in DM9000 programming guide and
37 application notes)
Remy Bohmera1013612008-06-03 15:26:21 +020038 - Added autodetect of databus width.
Remy Bohmer134e2662008-06-03 15:26:22 +020039 - Made debug code compile again.
Remy Bohmeracba3182008-06-03 15:26:23 +020040 - Adapt eth_send such that it matches the DM9000*
41 application notes. Needed to make it work properly
42 for DM9000A.
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +020043 - Adapted reset procedure to match DM9000 application
44 notes (i.e. double reset)
Remy Bohmer98291e22008-06-03 15:26:26 +020045 - some minor code cleanups
Remy Bohmera1013612008-06-03 15:26:21 +020046 These changes are tested with DM9000{A,EP,E} together
Remy Bohmere5a3bc22009-05-03 12:11:40 +020047 with a 200MHz Atmel AT91SAM9261 core
wdenk281e00a2004-08-01 22:48:16 +000048
Andrew Dyerd26b7392008-08-26 17:03:38 -050049TODO: external MII is not functional, only internal at the moment.
wdenk281e00a2004-08-01 22:48:16 +000050*/
51
52#include <common.h>
53#include <command.h>
54#include <net.h>
55#include <asm/io.h>
Remy Bohmere5a3bc22009-05-03 12:11:40 +020056#include <dm9000.h>
Simon Glassc05ed002020-05-10 11:40:11 -060057#include <linux/delay.h>
wdenk281e00a2004-08-01 22:48:16 +000058
wdenk281e00a2004-08-01 22:48:16 +000059#include "dm9000x.h"
60
wdenk281e00a2004-08-01 22:48:16 +000061/* Structure/enum declaration ------------------------------- */
62typedef struct board_info {
63 u32 runt_length_counter; /* counter: RX length < 64byte */
64 u32 long_length_counter; /* counter: RX length > 1514byte */
65 u32 reset_counter; /* counter: RESET */
66 u32 reset_tx_timeout; /* RESET caused by TX Timeout */
67 u32 reset_rx_status; /* RESET caused by RX Statsus wrong */
68 u16 tx_pkt_cnt;
69 u16 queue_start_addr;
70 u16 dbug_cnt;
71 u8 phy_addr;
72 u8 device_wait_reset; /* device state */
wdenk281e00a2004-08-01 22:48:16 +000073 unsigned char srom[128];
Remy Bohmer0e38c932008-06-05 13:03:36 +020074 void (*outblk)(volatile void *data_ptr, int count);
Remy Bohmera1013612008-06-03 15:26:21 +020075 void (*inblk)(void *data_ptr, int count);
Marek Vasutd8f21b22022-04-13 04:15:25 +020076 void (*rx_status)(u16 *rxstatus, u16 *rxlen);
Remy Bohmer60f61e62009-05-02 21:49:18 +020077 struct eth_device netdev;
Remy Bohmer98291e22008-06-03 15:26:26 +020078} board_info_t;
Remy Bohmera1013612008-06-03 15:26:21 +020079static board_info_t dm9000_info;
wdenk281e00a2004-08-01 22:48:16 +000080
Remy Bohmer60f61e62009-05-02 21:49:18 +020081
wdenk281e00a2004-08-01 22:48:16 +000082/* function declaration ------------------------------------- */
wdenk281e00a2004-08-01 22:48:16 +000083static int dm9000_probe(void);
Andy Fleming09c04c22011-03-22 22:49:13 -050084static u16 dm9000_phy_read(int);
85static void dm9000_phy_write(int, u16);
Marek Vasutff61d4e2022-04-13 04:15:23 +020086static u8 dm9000_ior(int);
87static void dm9000_iow(int reg, u8 value);
wdenk281e00a2004-08-01 22:48:16 +000088
89/* DM9000 network board routine ---------------------------- */
Jason Jin5c1d0822011-08-25 15:46:43 +080090#ifndef CONFIG_DM9000_BYTE_SWAPPED
Marek Vasutff61d4e2022-04-13 04:15:23 +020091#define dm9000_outb(d,r) writeb(d, (volatile u8 *)(r))
92#define dm9000_outw(d,r) writew(d, (volatile u16 *)(r))
93#define dm9000_outl(d,r) writel(d, (volatile u32 *)(r))
94#define dm9000_inb(r) readb((volatile u8 *)(r))
95#define dm9000_inw(r) readw((volatile u16 *)(r))
96#define dm9000_inl(r) readl((volatile u32 *)(r))
Jason Jin5c1d0822011-08-25 15:46:43 +080097#else
Marek Vasutff61d4e2022-04-13 04:15:23 +020098#define dm9000_outb(d, r) __raw_writeb(d, r)
99#define dm9000_outw(d, r) __raw_writew(d, r)
100#define dm9000_outl(d, r) __raw_writel(d, r)
101#define dm9000_inb(r) __raw_readb(r)
102#define dm9000_inw(r) __raw_readw(r)
103#define dm9000_inl(r) __raw_readl(r)
Jason Jin5c1d0822011-08-25 15:46:43 +0800104#endif
wdenk281e00a2004-08-01 22:48:16 +0000105
Marek Vasutc7b7ee52022-04-13 04:15:27 +0200106#ifdef DEBUG
107static void dm9000_dump_packet(const char *func, u8 *packet, int length)
108{
109 int i;
110
111 printf("%s: length: %d\n", func, length);
112
113 for (i = 0; i < length; i++) {
114 if (i % 8 == 0)
115 printf("\n%s: %02x: ", func, i);
116 printf("%02x ", packet[i]);
117 }
118
119 printf("\n");
120}
121#else
122static void dm9000_dump_packet(const char *func, u8 *packet, int length) {}
123#endif
124
Remy Bohmer0e38c932008-06-05 13:03:36 +0200125static void dm9000_outblk_8bit(volatile void *data_ptr, int count)
Remy Bohmera1013612008-06-03 15:26:21 +0200126{
127 int i;
128 for (i = 0; i < count; i++)
Marek Vasutff61d4e2022-04-13 04:15:23 +0200129 dm9000_outb((((u8 *) data_ptr)[i] & 0xff), DM9000_DATA);
Remy Bohmera1013612008-06-03 15:26:21 +0200130}
131
Remy Bohmer0e38c932008-06-05 13:03:36 +0200132static void dm9000_outblk_16bit(volatile void *data_ptr, int count)
Remy Bohmera1013612008-06-03 15:26:21 +0200133{
134 int i;
135 u32 tmplen = (count + 1) / 2;
136
137 for (i = 0; i < tmplen; i++)
Marek Vasutff61d4e2022-04-13 04:15:23 +0200138 dm9000_outw(((u16 *) data_ptr)[i], DM9000_DATA);
Remy Bohmera1013612008-06-03 15:26:21 +0200139}
Remy Bohmer0e38c932008-06-05 13:03:36 +0200140static void dm9000_outblk_32bit(volatile void *data_ptr, int count)
Remy Bohmera1013612008-06-03 15:26:21 +0200141{
142 int i;
143 u32 tmplen = (count + 3) / 4;
144
145 for (i = 0; i < tmplen; i++)
Marek Vasutff61d4e2022-04-13 04:15:23 +0200146 dm9000_outl(((u32 *) data_ptr)[i], DM9000_DATA);
Remy Bohmera1013612008-06-03 15:26:21 +0200147}
148
149static void dm9000_inblk_8bit(void *data_ptr, int count)
150{
151 int i;
152 for (i = 0; i < count; i++)
Marek Vasutff61d4e2022-04-13 04:15:23 +0200153 ((u8 *) data_ptr)[i] = dm9000_inb(DM9000_DATA);
Remy Bohmera1013612008-06-03 15:26:21 +0200154}
155
156static void dm9000_inblk_16bit(void *data_ptr, int count)
157{
158 int i;
159 u32 tmplen = (count + 1) / 2;
160
161 for (i = 0; i < tmplen; i++)
Marek Vasutff61d4e2022-04-13 04:15:23 +0200162 ((u16 *) data_ptr)[i] = dm9000_inw(DM9000_DATA);
Remy Bohmera1013612008-06-03 15:26:21 +0200163}
164static void dm9000_inblk_32bit(void *data_ptr, int count)
165{
166 int i;
167 u32 tmplen = (count + 3) / 4;
168
169 for (i = 0; i < tmplen; i++)
Marek Vasutff61d4e2022-04-13 04:15:23 +0200170 ((u32 *) data_ptr)[i] = dm9000_inl(DM9000_DATA);
Remy Bohmera1013612008-06-03 15:26:21 +0200171}
172
Marek Vasutd8f21b22022-04-13 04:15:25 +0200173static void dm9000_rx_status_32bit(u16 *rxstatus, u16 *rxlen)
Remy Bohmera1013612008-06-03 15:26:21 +0200174{
Remy Bohmerd6ee5fa2008-06-04 10:47:25 +0200175 u32 tmpdata;
Remy Bohmera1013612008-06-03 15:26:21 +0200176
Marek Vasutff61d4e2022-04-13 04:15:23 +0200177 dm9000_outb(DM9000_MRCMD, DM9000_IO);
Remy Bohmera1013612008-06-03 15:26:21 +0200178
Marek Vasutff61d4e2022-04-13 04:15:23 +0200179 tmpdata = dm9000_inl(DM9000_DATA);
Marek Vasutd8f21b22022-04-13 04:15:25 +0200180 *rxstatus = __le16_to_cpu(tmpdata);
181 *rxlen = __le16_to_cpu(tmpdata >> 16);
Remy Bohmera1013612008-06-03 15:26:21 +0200182}
183
Marek Vasutd8f21b22022-04-13 04:15:25 +0200184static void dm9000_rx_status_16bit(u16 *rxstatus, u16 *rxlen)
Remy Bohmera1013612008-06-03 15:26:21 +0200185{
Marek Vasutff61d4e2022-04-13 04:15:23 +0200186 dm9000_outb(DM9000_MRCMD, DM9000_IO);
Remy Bohmera1013612008-06-03 15:26:21 +0200187
Marek Vasutd8f21b22022-04-13 04:15:25 +0200188 *rxstatus = __le16_to_cpu(dm9000_inw(DM9000_DATA));
189 *rxlen = __le16_to_cpu(dm9000_inw(DM9000_DATA));
Remy Bohmera1013612008-06-03 15:26:21 +0200190}
191
Marek Vasutd8f21b22022-04-13 04:15:25 +0200192static void dm9000_rx_status_8bit(u16 *rxstatus, u16 *rxlen)
Remy Bohmera1013612008-06-03 15:26:21 +0200193{
Marek Vasutff61d4e2022-04-13 04:15:23 +0200194 dm9000_outb(DM9000_MRCMD, DM9000_IO);
Remy Bohmera1013612008-06-03 15:26:21 +0200195
Marek Vasutd8f21b22022-04-13 04:15:25 +0200196 *rxstatus =
Marek Vasutff61d4e2022-04-13 04:15:23 +0200197 __le16_to_cpu(dm9000_inb(DM9000_DATA) +
198 (dm9000_inb(DM9000_DATA) << 8));
Marek Vasutd8f21b22022-04-13 04:15:25 +0200199 *rxlen =
Marek Vasutff61d4e2022-04-13 04:15:23 +0200200 __le16_to_cpu(dm9000_inb(DM9000_DATA) +
201 (dm9000_inb(DM9000_DATA) << 8));
Remy Bohmera1013612008-06-03 15:26:21 +0200202}
wdenk281e00a2004-08-01 22:48:16 +0000203
204/*
205 Search DM9000 board, allocate space and register it
206*/
207int
208dm9000_probe(void)
209{
210 u32 id_val;
Marek Vasutff61d4e2022-04-13 04:15:23 +0200211 id_val = dm9000_ior(DM9000_VIDL);
212 id_val |= dm9000_ior(DM9000_VIDH) << 8;
213 id_val |= dm9000_ior(DM9000_PIDL) << 16;
214 id_val |= dm9000_ior(DM9000_PIDH) << 24;
wdenk281e00a2004-08-01 22:48:16 +0000215 if (id_val == DM9000_ID) {
216 printf("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE,
217 id_val);
218 return 0;
219 } else {
220 printf("dm9000 not found at 0x%08x id: 0x%08x\n",
221 CONFIG_DM9000_BASE, id_val);
222 return -1;
223 }
224}
225
wdenk281e00a2004-08-01 22:48:16 +0000226/* General Purpose dm9000 reset routine */
227static void
228dm9000_reset(void)
229{
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200230 debug("resetting DM9000\n");
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200231
232 /* Reset DM9000,
233 see DM9000 Application Notes V1.22 Jun 11, 2004 page 29 */
234
Andrew Dyerd26b7392008-08-26 17:03:38 -0500235 /* DEBUG: Make all GPIO0 outputs, all others inputs */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200236 dm9000_iow(DM9000_GPCR, GPCR_GPIO0_OUT);
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200237 /* Step 1: Power internal PHY by writing 0 to GPIO0 pin */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200238 dm9000_iow(DM9000_GPR, 0);
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200239 /* Step 2: Software reset */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200240 dm9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200241
242 do {
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200243 debug("resetting the DM9000, 1st reset\n");
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200244 udelay(25); /* Wait at least 20 us */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200245 } while (dm9000_ior(DM9000_NCR) & 1);
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200246
Marek Vasutff61d4e2022-04-13 04:15:23 +0200247 dm9000_iow(DM9000_NCR, 0);
248 dm9000_iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); /* Issue a second reset */
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200249
250 do {
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200251 debug("resetting the DM9000, 2nd reset\n");
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200252 udelay(25); /* Wait at least 20 us */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200253 } while (dm9000_ior(DM9000_NCR) & 1);
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200254
255 /* Check whether the ethernet controller is present */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200256 if ((dm9000_ior(DM9000_PIDL) != 0x0) ||
257 (dm9000_ior(DM9000_PIDH) != 0x90))
Remy Bohmerfbcb7ec2008-06-03 15:26:24 +0200258 printf("ERROR: resetting DM9000 -> not responding\n");
wdenk281e00a2004-08-01 22:48:16 +0000259}
260
Remy Bohmer60f61e62009-05-02 21:49:18 +0200261/* Initialize dm9000 board
wdenk281e00a2004-08-01 22:48:16 +0000262*/
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900263static int dm9000_init(struct eth_device *dev, struct bd_info *bd)
wdenk281e00a2004-08-01 22:48:16 +0000264{
265 int i, oft, lnk;
Remy Bohmera1013612008-06-03 15:26:21 +0200266 u8 io_mode;
267 struct board_info *db = &dm9000_info;
268
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200269 debug("%s\n", __func__);
wdenk281e00a2004-08-01 22:48:16 +0000270
271 /* RESET device */
272 dm9000_reset();
Andrew Dyerd26b7392008-08-26 17:03:38 -0500273
274 if (dm9000_probe() < 0)
275 return -1;
wdenk281e00a2004-08-01 22:48:16 +0000276
Remy Bohmera1013612008-06-03 15:26:21 +0200277 /* Auto-detect 8/16/32 bit mode, ISR Bit 6+7 indicate bus width */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200278 io_mode = dm9000_ior(DM9000_ISR) >> 6;
Remy Bohmera1013612008-06-03 15:26:21 +0200279
280 switch (io_mode) {
281 case 0x0: /* 16-bit mode */
282 printf("DM9000: running in 16 bit mode\n");
283 db->outblk = dm9000_outblk_16bit;
284 db->inblk = dm9000_inblk_16bit;
285 db->rx_status = dm9000_rx_status_16bit;
286 break;
287 case 0x01: /* 32-bit mode */
288 printf("DM9000: running in 32 bit mode\n");
289 db->outblk = dm9000_outblk_32bit;
290 db->inblk = dm9000_inblk_32bit;
291 db->rx_status = dm9000_rx_status_32bit;
292 break;
293 case 0x02: /* 8 bit mode */
294 printf("DM9000: running in 8 bit mode\n");
295 db->outblk = dm9000_outblk_8bit;
296 db->inblk = dm9000_inblk_8bit;
297 db->rx_status = dm9000_rx_status_8bit;
298 break;
299 default:
300 /* Assume 8 bit mode, will probably not work anyway */
301 printf("DM9000: Undefined IO-mode:0x%x\n", io_mode);
302 db->outblk = dm9000_outblk_8bit;
303 db->inblk = dm9000_inblk_8bit;
304 db->rx_status = dm9000_rx_status_8bit;
305 break;
306 }
307
Andrew Dyerd26b7392008-08-26 17:03:38 -0500308 /* Program operating register, only internal phy supported */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200309 dm9000_iow(DM9000_NCR, 0x0);
Remy Bohmer98291e22008-06-03 15:26:26 +0200310 /* TX Polling clear */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200311 dm9000_iow(DM9000_TCR, 0);
Remy Bohmer98291e22008-06-03 15:26:26 +0200312 /* Less 3Kb, 200us */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200313 dm9000_iow(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);
Remy Bohmer98291e22008-06-03 15:26:26 +0200314 /* Flow Control : High/Low Water */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200315 dm9000_iow(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
Remy Bohmer98291e22008-06-03 15:26:26 +0200316 /* SH FIXME: This looks strange! Flow Control */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200317 dm9000_iow(DM9000_FCR, 0x0);
Remy Bohmer98291e22008-06-03 15:26:26 +0200318 /* Special Mode */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200319 dm9000_iow(DM9000_SMCR, 0);
Remy Bohmer98291e22008-06-03 15:26:26 +0200320 /* clear TX status */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200321 dm9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
Remy Bohmer98291e22008-06-03 15:26:26 +0200322 /* Clear interrupt status */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200323 dm9000_iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
wdenk281e00a2004-08-01 22:48:16 +0000324
Ben Warren07754372009-10-21 21:53:39 -0700325 printf("MAC: %pM\n", dev->enetaddr);
Joe Hershberger0adb5b72015-04-08 01:41:04 -0500326 if (!is_valid_ethaddr(dev->enetaddr)) {
Andrew Ruderc583ee12013-10-22 19:09:02 -0500327 printf("WARNING: Bad MAC address (uninitialized EEPROM?)\n");
Andrew Ruderc583ee12013-10-22 19:09:02 -0500328 }
Andrew Dyerd26b7392008-08-26 17:03:38 -0500329
330 /* fill device MAC address registers */
331 for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)
Marek Vasutff61d4e2022-04-13 04:15:23 +0200332 dm9000_iow(oft, dev->enetaddr[i]);
wdenk281e00a2004-08-01 22:48:16 +0000333 for (i = 0, oft = 0x16; i < 8; i++, oft++)
Marek Vasutff61d4e2022-04-13 04:15:23 +0200334 dm9000_iow(oft, 0xff);
wdenk281e00a2004-08-01 22:48:16 +0000335
336 /* read back mac, just to be sure */
337 for (i = 0, oft = 0x10; i < 6; i++, oft++)
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200338 debug("%02x:", dm9000_ior(oft));
339 debug("\n");
wdenk281e00a2004-08-01 22:48:16 +0000340
341 /* Activate DM9000 */
Remy Bohmer98291e22008-06-03 15:26:26 +0200342 /* RX enable */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200343 dm9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
Remy Bohmer98291e22008-06-03 15:26:26 +0200344 /* Enable TX/RX interrupt mask */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200345 dm9000_iow(DM9000_IMR, IMR_PAR);
Remy Bohmer98291e22008-06-03 15:26:26 +0200346
wdenk281e00a2004-08-01 22:48:16 +0000347 i = 0;
Andy Fleming09c04c22011-03-22 22:49:13 -0500348 while (!(dm9000_phy_read(1) & 0x20)) { /* autonegation complete bit */
wdenk281e00a2004-08-01 22:48:16 +0000349 udelay(1000);
350 i++;
351 if (i == 10000) {
352 printf("could not establish link\n");
353 return 0;
354 }
355 }
356
357 /* see what we've got */
Andy Fleming09c04c22011-03-22 22:49:13 -0500358 lnk = dm9000_phy_read(17) >> 12;
wdenk281e00a2004-08-01 22:48:16 +0000359 printf("operating at ");
360 switch (lnk) {
361 case 1:
362 printf("10M half duplex ");
363 break;
364 case 2:
365 printf("10M full duplex ");
366 break;
367 case 4:
368 printf("100M half duplex ");
369 break;
370 case 8:
371 printf("100M full duplex ");
372 break;
373 default:
374 printf("unknown: %d ", lnk);
375 break;
376 }
377 printf("mode\n");
378 return 0;
379}
380
381/*
382 Hardware start transmission.
383 Send a packet to media from the upper layer.
384*/
Joe Hershberger7f9a8a62012-05-21 14:45:23 +0000385static int dm9000_send(struct eth_device *netdev, void *packet, int length)
wdenk281e00a2004-08-01 22:48:16 +0000386{
wdenk281e00a2004-08-01 22:48:16 +0000387 int tmo;
Remy Bohmera1013612008-06-03 15:26:21 +0200388 struct board_info *db = &dm9000_info;
389
Marek Vasutc7b7ee52022-04-13 04:15:27 +0200390 dm9000_dump_packet(__func__ , packet, length);
wdenk281e00a2004-08-01 22:48:16 +0000391
Marek Vasutff61d4e2022-04-13 04:15:23 +0200392 dm9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
Remy Bohmeracba3182008-06-03 15:26:23 +0200393
wdenk281e00a2004-08-01 22:48:16 +0000394 /* Move data to DM9000 TX RAM */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200395 dm9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */
wdenk281e00a2004-08-01 22:48:16 +0000396
Remy Bohmera1013612008-06-03 15:26:21 +0200397 /* push the data to the TX-fifo */
Remy Bohmer0e38c932008-06-05 13:03:36 +0200398 (db->outblk)(packet, length);
wdenk281e00a2004-08-01 22:48:16 +0000399
400 /* Set TX length to DM9000 */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200401 dm9000_iow(DM9000_TXPLL, length & 0xff);
402 dm9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
wdenk281e00a2004-08-01 22:48:16 +0000403
404 /* Issue TX polling command */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200405 dm9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
wdenk281e00a2004-08-01 22:48:16 +0000406
407 /* wait for end of transmission */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200408 tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
Marek Vasutff61d4e2022-04-13 04:15:23 +0200409 while ( !(dm9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
410 !(dm9000_ior(DM9000_ISR) & IMR_PTM) ) {
wdenk281e00a2004-08-01 22:48:16 +0000411 if (get_timer(0) >= tmo) {
412 printf("transmission timeout\n");
413 break;
414 }
415 }
Marek Vasutff61d4e2022-04-13 04:15:23 +0200416 dm9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */
Remy Bohmeracba3182008-06-03 15:26:23 +0200417
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200418 debug("transmit done\n\n");
wdenk281e00a2004-08-01 22:48:16 +0000419 return 0;
420}
421
422/*
423 Stop the interface.
424 The interface is stopped when it is brought.
425*/
Remy Bohmer60f61e62009-05-02 21:49:18 +0200426static void dm9000_halt(struct eth_device *netdev)
wdenk281e00a2004-08-01 22:48:16 +0000427{
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200428 debug("%s\n", __func__);
wdenk281e00a2004-08-01 22:48:16 +0000429
430 /* RESET devie */
Andy Fleming09c04c22011-03-22 22:49:13 -0500431 dm9000_phy_write(0, 0x8000); /* PHY RESET */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200432 dm9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
433 dm9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
434 dm9000_iow(DM9000_RCR, 0x00); /* Disable RX */
wdenk281e00a2004-08-01 22:48:16 +0000435}
436
437/*
438 Received a packet and pass to upper layer
439*/
Remy Bohmer60f61e62009-05-02 21:49:18 +0200440static int dm9000_rx(struct eth_device *netdev)
wdenk281e00a2004-08-01 22:48:16 +0000441{
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500442 u8 rxbyte;
443 u8 *rdptr = (u8 *)net_rx_packets[0];
Marek Vasutd8f21b22022-04-13 04:15:25 +0200444 u16 rxstatus, rxlen = 0;
Remy Bohmera1013612008-06-03 15:26:21 +0200445 struct board_info *db = &dm9000_info;
wdenk281e00a2004-08-01 22:48:16 +0000446
Remy Bohmer850ba752008-06-03 15:26:25 +0200447 /* Check packet ready or not, we must check
448 the ISR status first for DM9000A */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200449 if (!(dm9000_ior(DM9000_ISR) & 0x01)) /* Rx-ISR bit must be set. */
wdenk281e00a2004-08-01 22:48:16 +0000450 return 0;
451
Marek Vasutff61d4e2022-04-13 04:15:23 +0200452 dm9000_iow(DM9000_ISR, 0x01); /* clear PR status latched in bit 0 */
wdenk281e00a2004-08-01 22:48:16 +0000453
Remy Bohmer850ba752008-06-03 15:26:25 +0200454 /* There is _at least_ 1 package in the fifo, read them all */
455 for (;;) {
Marek Vasutff61d4e2022-04-13 04:15:23 +0200456 dm9000_ior(DM9000_MRCMDX); /* Dummy read */
wdenk281e00a2004-08-01 22:48:16 +0000457
Remy Bohmer0e38c932008-06-05 13:03:36 +0200458 /* Get most updated data,
459 only look at bits 0:1, See application notes DM9000 */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200460 rxbyte = dm9000_inb(DM9000_DATA) & 0x03;
wdenk281e00a2004-08-01 22:48:16 +0000461
Remy Bohmer850ba752008-06-03 15:26:25 +0200462 /* Status check: this byte must be 0 or 1 */
463 if (rxbyte > DM9000_PKT_RDY) {
Marek Vasutff61d4e2022-04-13 04:15:23 +0200464 dm9000_iow(DM9000_RCR, 0x00); /* Stop Device */
465 dm9000_iow(DM9000_ISR, 0x80); /* Stop INT request */
Remy Bohmer850ba752008-06-03 15:26:25 +0200466 printf("DM9000 error: status check fail: 0x%x\n",
467 rxbyte);
468 return 0;
wdenk281e00a2004-08-01 22:48:16 +0000469 }
wdenk281e00a2004-08-01 22:48:16 +0000470
Remy Bohmer850ba752008-06-03 15:26:25 +0200471 if (rxbyte != DM9000_PKT_RDY)
472 return 0; /* No packet received, ignore */
473
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200474 debug("receiving packet\n");
Remy Bohmer850ba752008-06-03 15:26:25 +0200475
476 /* A packet ready now & Get status/length */
Marek Vasutd8f21b22022-04-13 04:15:25 +0200477 (db->rx_status)(&rxstatus, &rxlen);
Remy Bohmer850ba752008-06-03 15:26:25 +0200478
Marek Vasutd8f21b22022-04-13 04:15:25 +0200479 debug("rx status: 0x%04x rx len: %d\n", rxstatus, rxlen);
Remy Bohmer850ba752008-06-03 15:26:25 +0200480
481 /* Move data from DM9000 */
482 /* Read received packet from RX SRAM */
Marek Vasutd8f21b22022-04-13 04:15:25 +0200483 (db->inblk)(rdptr, rxlen);
Remy Bohmer850ba752008-06-03 15:26:25 +0200484
Marek Vasutd8f21b22022-04-13 04:15:25 +0200485 if ((rxstatus & 0xbf00) || (rxlen < 0x40)
486 || (rxlen > DM9000_PKT_MAX)) {
487 if (rxstatus & 0x100) {
Remy Bohmer850ba752008-06-03 15:26:25 +0200488 printf("rx fifo error\n");
489 }
Marek Vasutd8f21b22022-04-13 04:15:25 +0200490 if (rxstatus & 0x200) {
Remy Bohmer850ba752008-06-03 15:26:25 +0200491 printf("rx crc error\n");
492 }
Marek Vasutd8f21b22022-04-13 04:15:25 +0200493 if (rxstatus & 0x8000) {
Remy Bohmer850ba752008-06-03 15:26:25 +0200494 printf("rx length error\n");
495 }
Marek Vasutd8f21b22022-04-13 04:15:25 +0200496 if (rxlen > DM9000_PKT_MAX) {
Remy Bohmer850ba752008-06-03 15:26:25 +0200497 printf("rx length too big\n");
498 dm9000_reset();
499 }
500 } else {
Marek Vasutc7b7ee52022-04-13 04:15:27 +0200501 dm9000_dump_packet(__func__ , rdptr, rxlen);
Remy Bohmer850ba752008-06-03 15:26:25 +0200502
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200503 debug("passing packet to upper layer\n");
Marek Vasutd8f21b22022-04-13 04:15:25 +0200504 net_process_received_packet(net_rx_packets[0], rxlen);
Remy Bohmer850ba752008-06-03 15:26:25 +0200505 }
wdenk281e00a2004-08-01 22:48:16 +0000506 }
507 return 0;
508}
509
510/*
511 Read a word data from SROM
512*/
Remy Bohmere5a3bc22009-05-03 12:11:40 +0200513#if !defined(CONFIG_DM9000_NO_SROM)
514void dm9000_read_srom_word(int offset, u8 *to)
wdenk281e00a2004-08-01 22:48:16 +0000515{
Marek Vasutff61d4e2022-04-13 04:15:23 +0200516 dm9000_iow(DM9000_EPAR, offset);
517 dm9000_iow(DM9000_EPCR, 0x4);
stefano babic5f470942007-08-21 15:50:33 +0200518 udelay(8000);
Marek Vasutff61d4e2022-04-13 04:15:23 +0200519 dm9000_iow(DM9000_EPCR, 0x0);
520 to[0] = dm9000_ior(DM9000_EPDRL);
521 to[1] = dm9000_ior(DM9000_EPDRH);
wdenk281e00a2004-08-01 22:48:16 +0000522}
523
Remy Bohmere5a3bc22009-05-03 12:11:40 +0200524void dm9000_write_srom_word(int offset, u16 val)
stefano babic5e5803e2007-08-30 23:01:49 +0200525{
Marek Vasutff61d4e2022-04-13 04:15:23 +0200526 dm9000_iow(DM9000_EPAR, offset);
527 dm9000_iow(DM9000_EPDRH, ((val >> 8) & 0xff));
528 dm9000_iow(DM9000_EPDRL, (val & 0xff));
529 dm9000_iow(DM9000_EPCR, 0x12);
stefano babic5e5803e2007-08-30 23:01:49 +0200530 udelay(8000);
Marek Vasutff61d4e2022-04-13 04:15:23 +0200531 dm9000_iow(DM9000_EPCR, 0);
stefano babic5e5803e2007-08-30 23:01:49 +0200532}
Remy Bohmere5a3bc22009-05-03 12:11:40 +0200533#endif
stefano babic5e5803e2007-08-30 23:01:49 +0200534
Ben Warren07754372009-10-21 21:53:39 -0700535static void dm9000_get_enetaddr(struct eth_device *dev)
536{
537#if !defined(CONFIG_DM9000_NO_SROM)
538 int i;
539 for (i = 0; i < 3; i++)
540 dm9000_read_srom_word(i, dev->enetaddr + (2 * i));
541#endif
542}
543
wdenk281e00a2004-08-01 22:48:16 +0000544/*
545 Read a byte from I/O port
546*/
547static u8
Marek Vasutff61d4e2022-04-13 04:15:23 +0200548dm9000_ior(int reg)
wdenk281e00a2004-08-01 22:48:16 +0000549{
Marek Vasutff61d4e2022-04-13 04:15:23 +0200550 dm9000_outb(reg, DM9000_IO);
551 return dm9000_inb(DM9000_DATA);
wdenk281e00a2004-08-01 22:48:16 +0000552}
553
554/*
555 Write a byte to I/O port
556*/
557static void
Marek Vasutff61d4e2022-04-13 04:15:23 +0200558dm9000_iow(int reg, u8 value)
wdenk281e00a2004-08-01 22:48:16 +0000559{
Marek Vasutff61d4e2022-04-13 04:15:23 +0200560 dm9000_outb(reg, DM9000_IO);
561 dm9000_outb(value, DM9000_DATA);
wdenk281e00a2004-08-01 22:48:16 +0000562}
563
564/*
565 Read a word from phyxcer
566*/
567static u16
Andy Fleming09c04c22011-03-22 22:49:13 -0500568dm9000_phy_read(int reg)
wdenk281e00a2004-08-01 22:48:16 +0000569{
570 u16 val;
571
572 /* Fill the phyxcer register into REG_0C */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200573 dm9000_iow(DM9000_EPAR, DM9000_PHY | reg);
574 dm9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
Remy Bohmer98291e22008-06-03 15:26:26 +0200575 udelay(100); /* Wait read complete */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200576 dm9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
577 val = (dm9000_ior(DM9000_EPDRH) << 8) | dm9000_ior(DM9000_EPDRL);
wdenk281e00a2004-08-01 22:48:16 +0000578
579 /* The read data keeps on REG_0D & REG_0E */
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200580 debug("dm9000_phy_read(0x%x): 0x%x\n", reg, val);
wdenk281e00a2004-08-01 22:48:16 +0000581 return val;
582}
583
584/*
585 Write a word to phyxcer
586*/
587static void
Andy Fleming09c04c22011-03-22 22:49:13 -0500588dm9000_phy_write(int reg, u16 value)
wdenk281e00a2004-08-01 22:48:16 +0000589{
590
591 /* Fill the phyxcer register into REG_0C */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200592 dm9000_iow(DM9000_EPAR, DM9000_PHY | reg);
wdenk281e00a2004-08-01 22:48:16 +0000593
594 /* Fill the written data into REG_0D & REG_0E */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200595 dm9000_iow(DM9000_EPDRL, (value & 0xff));
596 dm9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
597 dm9000_iow(DM9000_EPCR, 0xa); /* Issue phyxcer write command */
Remy Bohmer98291e22008-06-03 15:26:26 +0200598 udelay(500); /* Wait write complete */
Marek Vasutff61d4e2022-04-13 04:15:23 +0200599 dm9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer write command */
Marek Vasut42a7e0f2022-04-13 04:15:24 +0200600 debug("dm9000_phy_write(reg:0x%x, value:0x%x)\n", reg, value);
wdenk281e00a2004-08-01 22:48:16 +0000601}
Remy Bohmer60f61e62009-05-02 21:49:18 +0200602
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +0900603int dm9000_initialize(struct bd_info *bis)
Remy Bohmer60f61e62009-05-02 21:49:18 +0200604{
605 struct eth_device *dev = &(dm9000_info.netdev);
606
Ben Warren07754372009-10-21 21:53:39 -0700607 /* Load MAC address from EEPROM */
608 dm9000_get_enetaddr(dev);
609
Remy Bohmer60f61e62009-05-02 21:49:18 +0200610 dev->init = dm9000_init;
611 dev->halt = dm9000_halt;
612 dev->send = dm9000_send;
613 dev->recv = dm9000_rx;
Ben Whitten192bc692015-12-30 13:05:58 +0000614 strcpy(dev->name, "dm9000");
Remy Bohmer60f61e62009-05-02 21:49:18 +0200615
616 eth_register(dev);
617
618 return 0;
619}