blob: 3f1e770efe17f99081b16ff7647359e6de8f4d0b [file] [log] [blame]
wdenkfe8c2802002-11-03 00:38:21 +00001/*------------------------------------------------------------------------
2 . 3c589.c
3 . This is a driver for 3Com's 3C589 (Etherlink III) PCMCIA Ethernet device.
4 .
5 . (C) Copyright 2002
6 . Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7 . Rolf Offermanns <rof@sysgo.de>
8 .
9 . This program is free software; you can redistribute it and/or modify
10 . it under the terms of the GNU General Public License as published by
11 . the Free Software Foundation; either version 2 of the License, or
12 . (at your option) any later version.
13 .
14 . This program is distributed in the hope that it will be useful,
15 . but WITHOUT ANY WARRANTY; without even the implied warranty of
16 . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 . GNU General Public License for more details.
18 .
19 . You should have received a copy of the GNU General Public License
20 . along with this program; if not, write to the Free Software
21 . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 .
23 ----------------------------------------------------------------------------*/
24
25#include <common.h>
26#include <command.h>
27#include <net.h>
28
29#ifdef CONFIG_DRIVER_3C589
30
31#include "3c589.h"
32
33
34/* Use power-down feature of the chip */
35#define POWER_DOWN 0
36
37#define NO_AUTOPROBE
38
39static const char version[] =
40 "Your ad here! :P\n";
41
42
43#undef EL_DEBUG
44
45typedef unsigned char byte;
46typedef unsigned short word;
47typedef unsigned long int dword;
48/*------------------------------------------------------------------------
49 .
50 . Configuration options, for the experienced user to change.
51 .
52 -------------------------------------------------------------------------*/
53
54/*
55 . Wait time for memory to be free. This probably shouldn't be
56 . tuned that much, as waiting for this means nothing else happens
57 . in the system
58*/
59#define MEMORY_WAIT_TIME 16
60
61
62#if (EL_DEBUG > 2 )
63#define PRINTK3(args...) printf(args)
64#else
65#define PRINTK3(args...)
66#endif
67
68#if EL_DEBUG > 1
69#define PRINTK2(args...) printf(args)
70#else
71#define PRINTK2(args...)
72#endif
73
74#ifdef EL_DEBUG
75#define PRINTK(args...) printf(args)
76#else
77#define PRINTK(args...)
78#endif
79
80#define outb(args...) mmio_outb(args)
81#define mmio_outb(value, addr) (*((volatile byte *)(addr)) = value)
82
83#define inb(args...) mmio_inb(args)
84#define mmio_inb(addr) (*((volatile byte *)(addr)))
85
86#define outw(args...) mmio_outw(args)
87#define mmio_outw(value, addr) (*((volatile word *)(addr)) = value)
88
89#define inw(args...) mmio_inw(args)
90#define mmio_inw(addr) (*((volatile word *)(addr)))
91
92#define outsw(args...) mmio_outsw(args)
93#define mmio_outsw(r,b,l) ({ int __i; \
94 word *__b2; \
95 __b2 = (word *) b; \
96 for (__i = 0; __i < l; __i++) { \
97 mmio_outw( *(__b2 + __i), r); \
98 } \
99 })
100
101#define insw(args...) mmio_insw(args)
Wolfgang Denka1be4762008-05-20 16:00:29 +0200102#define mmio_insw(r,b,l) ({ int __i ; \
wdenkfe8c2802002-11-03 00:38:21 +0000103 word *__b2; \
wdenk57b2d802003-06-27 21:31:46 +0000104 __b2 = (word *) b; \
105 for (__i = 0; __i < l; __i++) { \
wdenkfe8c2802002-11-03 00:38:21 +0000106 *(__b2 + __i) = mmio_inw(r); \
107 mmio_inw(0); \
108 }; \
109 })
110
111/*------------------------------------------------------------------------
112 .
113 . The internal workings of the driver. If you are changing anything
114 . here with the 3Com stuff, you should have the datasheet and know
115 . what you are doing.
116 .
117 -------------------------------------------------------------------------*/
118#define EL_BASE_ADDR 0x20000000
119
120
121/* Offsets from base I/O address. */
122#define EL3_DATA 0x00
123#define EL3_TIMER 0x0a
124#define EL3_CMD 0x0e
125#define EL3_STATUS 0x0e
126
127#define EEPROM_READ 0x0080
128
129#define EL3WINDOW(win_num) mmio_outw(SelectWindow + (win_num), EL_BASE_ADDR + EL3_CMD)
130
131/* The top five bits written to EL3_CMD are a command, the lower
132 11 bits are the parameter, if applicable. */
133enum c509cmd {
134 TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
135 RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
136 TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
137 FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
138 SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
139 SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
140 StatsDisable = 22<<11, StopCoax = 23<<11,
141};
142
143enum c509status {
144 IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
145 TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
146 IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000
147};
148
149/* The SetRxFilter command accepts the following classes: */
150enum RxFilter {
151 RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
152};
153
154/* Register window 1 offsets, the window used in normal operation. */
155#define TX_FIFO 0x00
156#define RX_FIFO 0x00
Wolfgang Denka1be4762008-05-20 16:00:29 +0200157#define RX_STATUS 0x08
158#define TX_STATUS 0x0B
wdenkfe8c2802002-11-03 00:38:21 +0000159#define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */
160
161
162/*
163 Read a word from the EEPROM using the regular EEPROM access register.
164 Assume that we are in register window zero.
165*/
166static word read_eeprom(dword ioaddr, int index)
167{
168 int i;
169 outw(EEPROM_READ + index, ioaddr + 0xa);
170 /* Reading the eeprom takes 162 us */
171 for (i = 1620; i >= 0; i--)
172 if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0)
173 break;
174 return inw(ioaddr + 0xc);
175}
176
177static void el_get_mac_addr( unsigned char *mac_addr )
178{
179 int i;
180 union
181 {
182 word w;
183 unsigned char b[2];
184 } wrd;
185 unsigned char old_window = inw( EL_BASE_ADDR + EL3_STATUS ) >> 13;
186 GO_WINDOW(0);
187 VX_BUSY_WAIT;
188 for (i = 0; i < 3; i++)
189 {
190 wrd.w = read_eeprom(EL_BASE_ADDR, 0xa+i);
191#ifdef __BIG_ENDIAN
192 mac_addr[2*i] = wrd.b[0];
193 mac_addr[2*i+1] = wrd.b[1];
194#else
195 mac_addr[2*i] = wrd.b[1];
196 mac_addr[2*i+1] = wrd.b[0];
197#endif
198 }
199 GO_WINDOW(old_window);
200 VX_BUSY_WAIT;
201}
202
203
204#if EL_DEBUG > 1
205static void print_packet( byte * buf, int length )
206{
wdenk57b2d802003-06-27 21:31:46 +0000207 int i;
208 int remainder;
209 int lines;
wdenkfe8c2802002-11-03 00:38:21 +0000210
wdenk57b2d802003-06-27 21:31:46 +0000211 PRINTK2("Packet of length %d \n", length );
wdenkfe8c2802002-11-03 00:38:21 +0000212
wdenk57b2d802003-06-27 21:31:46 +0000213 lines = length / 16;
214 remainder = length % 16;
wdenkfe8c2802002-11-03 00:38:21 +0000215
wdenk57b2d802003-06-27 21:31:46 +0000216 for ( i = 0; i < lines ; i ++ ) {
217 int cur;
wdenkfe8c2802002-11-03 00:38:21 +0000218
wdenk57b2d802003-06-27 21:31:46 +0000219 for ( cur = 0; cur < 8; cur ++ ) {
220 byte a, b;
wdenkfe8c2802002-11-03 00:38:21 +0000221
wdenk57b2d802003-06-27 21:31:46 +0000222 a = *(buf ++ );
223 b = *(buf ++ );
224 PRINTK2("%02x%02x ", a, b );
225 }
226 PRINTK2("\n");
227 }
228 for ( i = 0; i < remainder/2 ; i++ ) {
229 byte a, b;
wdenkfe8c2802002-11-03 00:38:21 +0000230
wdenk57b2d802003-06-27 21:31:46 +0000231 a = *(buf ++ );
232 b = *(buf ++ );
233 PRINTK2("%02x%02x ", a, b );
234 }
235 PRINTK2("\n");
wdenkfe8c2802002-11-03 00:38:21 +0000236}
237#endif /* EL_DEBUG > 1 */
238
239
wdenkfe8c2802002-11-03 00:38:21 +0000240/**************************************************************************
241ETH_RESET - Reset adapter
242***************************************************************************/
243static void el_reset(bd_t *bd)
244{
245 /***********************************************************
246 Reset 3Com 595 card
247 *************************************************************/
248 /* QUICK HACK
249 * - adjust timing for 3c589
250 * - enable io for PCMCIA */
251 outw(0x0004, 0xa0000018);
252 udelay(100);
253 outw(0x0041, 0x28010000);
254 udelay(100);
255
256 /* issue global reset */
257 outw(GLOBAL_RESET, BASE + VX_COMMAND);
258
259 /* must wait for at least 1ms */
260 udelay(100000000);
261
262 /* set mac addr */
263 {
264 unsigned char *mac_addr = bd->bi_enetaddr;
265 int i;
266
267 el_get_mac_addr( mac_addr );
268
269 GO_WINDOW(2);
270 VX_BUSY_WAIT;
271
272 printf("3C589 MAC Addr.: ");
273 for (i = 0; i < 6; i++)
274 {
275 printf("%02x", mac_addr[i]);
276 outb(mac_addr[i], BASE + VX_W2_ADDR_0 + i);
277 VX_BUSY_WAIT;
278 }
279 printf("\n\n");
280 }
281
282 /* set RX filter */
283 outw(SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST, BASE + VX_COMMAND);
284 VX_BUSY_WAIT;
285
286
287 /* set irq mask and read_zero */
288 outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
289 S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
290 VX_BUSY_WAIT;
291
292 outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
293 S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
294 VX_BUSY_WAIT;
295
296 /* enable TP Linkbeat */
297 GO_WINDOW(4);
298 VX_BUSY_WAIT;
299
300 outw( ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE);
301 VX_BUSY_WAIT;
302
303
304/*
305 * Attempt to get rid of any stray interrupts that occured during
306 * configuration. On the i386 this isn't possible because one may
307 * already be queued. However, a single stray interrupt is
308 * unimportant.
309 */
310
311 outw(ACK_INTR | 0xff, BASE + VX_COMMAND);
312 VX_BUSY_WAIT;
313
314 /* enable TX and RX */
315 outw( RX_ENABLE, BASE + VX_COMMAND );
316 VX_BUSY_WAIT;
317
318 outw( TX_ENABLE, BASE + VX_COMMAND );
319 VX_BUSY_WAIT;
320
321
322 /* print the diag. regs. */
323 PRINTK2("Diag. Regs\n");
324 PRINTK2("--> MEDIA_TYPE: %04x\n", inw(BASE + VX_W4_MEDIA_TYPE));
325 PRINTK2("--> NET_DIAG: %04x\n", inw(BASE + VX_W4_NET_DIAG));
326 PRINTK2("--> FIFO_DIAG: %04x\n", inw(BASE + VX_W4_FIFO_DIAG));
327 PRINTK2("--> CTRLR_STATUS: %04x\n", inw(BASE + VX_W4_CTRLR_STATUS));
328 PRINTK2("\n\n");
329
330 /* enter working mode */
331 GO_WINDOW(1);
332 VX_BUSY_WAIT;
333
334 /* wait for another 1ms */
335 udelay(100000000);
336}
337
338
339/*-----------------------------------------------------------------
340 .
341 . The driver can be entered at any of the following entry points.
342 .
343 .------------------------------------------------------------------ */
344
345extern int eth_init(bd_t *bd);
346extern void eth_halt(void);
347extern int eth_rx(void);
348extern int eth_send(volatile void *packet, int length);
349
350
351/*
352 ------------------------------------------------------------
353 .
354 . Internal routines
355 .
356 ------------------------------------------------------------
357*/
358
359int eth_init(bd_t *bd)
360{
361 el_reset(bd);
362 return 0;
363}
364
365void eth_halt() {
366 return;
367}
368
369#define EDEBUG 1
370
371
372/**************************************************************************
373ETH_POLL - Wait for a frame
374***************************************************************************/
375
376int eth_rx()
377{
378 word status, rx_status, packet_size;
379
380 VX_BUSY_WAIT;
381
382 status = inw( BASE + VX_STATUS );
383
384 if ( (status & S_RX_COMPLETE) == 0 ) return 0; /* nothing to do */
385
386 /* Packet waiting -> check RX_STATUS */
387 rx_status = inw( BASE + VX_W1_RX_STATUS );
388
389 if ( rx_status & ERR_RX )
390 {
391 /* error in packet -> discard */
392 PRINTK("[ERROR] Invalid packet -> discarding\n");
393 PRINTK("-- error code 0x%02x\n", rx_status & ERR_MASK);
394 PRINTK("-- rx bytes 0x%04d\n", rx_status & ((1<<11) - 1));
395 PRINTK("[ERROR] Invalid packet -> discarding\n");
396 outw( RX_DISCARD_TOP_PACK, BASE + VX_COMMAND );
397 return 0;
398 }
399
400 /* correct pack. waiting in fifo */
401 packet_size = rx_status & RX_BYTES_MASK;
402
403 PRINTK("Correct packet waiting in fifo, size: %d\n", packet_size);
404
405 {
406 volatile word *packet_start = (word *)(BASE + VX_W1_RX_PIO_RD_1);
407 word *RcvBuffer = (word *)(NetRxPackets[0]);
408 int wcount = 0;
409
410 for (wcount = 0; wcount < (packet_size >> 1); wcount++)
411 {
412 *RcvBuffer++ = *(packet_start);
413 }
414
415 /* handle odd packets */
416 if ( packet_size & 1 )
417 {
418 *RcvBuffer++ = *(packet_start);
419 }
420 }
421
422 /* fifo should now be empty (besides the padding bytes) */
423 if ( ((*((word *)(BASE + VX_W1_RX_STATUS))) & RX_BYTES_MASK) > 3 )
424 {
425 PRINTK("[ERROR] Fifo not empty after packet read (remaining pkts: %d)\n",
426 (((*(word *)(BASE + VX_W1_RX_STATUS))) & RX_BYTES_MASK));
427 }
428
429 /* discard packet */
430 *((word *)(BASE + VX_COMMAND)) = RX_DISCARD_TOP_PACK;
431
432 /* Pass Packets to upper Layer */
433 NetReceive(NetRxPackets[0], packet_size);
434 return packet_size;
435}
436
437
wdenkfe8c2802002-11-03 00:38:21 +0000438/**************************************************************************
439ETH_TRANSMIT - Transmit a frame
440***************************************************************************/
441static char padmap[] = {
442 0, 3, 2, 1};
443
444
445int eth_send(volatile void *packet, int length) {
446 int pad;
447 int status;
448 volatile word *buf = (word *)packet;
449 int dummy = 0;
450
451 /* padding stuff */
452 pad = padmap[length & 3];
453
454 PRINTK("eth_send(), length: %d\n", length);
455 /* drop acknowledgements */
456 while(( status=inb(EL_BASE_ADDR + VX_W1_TX_STATUS) )& TXS_COMPLETE ) {
457 if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
458 outw(TX_RESET, EL_BASE_ADDR + VX_COMMAND);
459 outw(TX_ENABLE, EL_BASE_ADDR + VX_COMMAND);
460 PRINTK("Bad status, resetting and reenabling transmitter\n");
461 }
462
463 outb(0x0, EL_BASE_ADDR + VX_W1_TX_STATUS);
464 }
465
466
467 while (inw(EL_BASE_ADDR + VX_W1_FREE_TX) < length + pad + 4) {
468 /* no room in FIFO */
469 if (dummy == 0)
470 {
471 PRINTK("No room in FIFO, waiting...\n");
472 dummy++;
473 }
474
475 }
476
477 PRINTK(" ---> FIFO ready\n");
478
479
480 outw(length, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1);
481
482 /* Second dword meaningless */
483 outw(0x0, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1);
484
485#if EL_DEBUG > 1
486 print_packet((byte *)buf, length);
487#endif
488
489 /* write packet */
490 {
491 unsigned int i, totw;
492
493 totw = ((length + 1) >> 1);
494 PRINTK("Buffer: (totw = %d)\n", totw);
495 for (i = 0; i < totw; i++) {
496 outw( *(buf+i), EL_BASE_ADDR + VX_W1_TX_PIO_WR_1);
497 udelay(10);
498 }
499 if(totw & 1)
500 { /* pad to double word length */
501 outw( 0, EL_BASE_ADDR + VX_W1_TX_PIO_WR_1);
502 udelay(10);
503 }
504 PRINTK("\n\n");
505 }
506
wdenk57b2d802003-06-27 21:31:46 +0000507 /* wait for Tx complete */
wdenkfe8c2802002-11-03 00:38:21 +0000508 PRINTK("Waiting for Tx to complete...\n");
wdenk57b2d802003-06-27 21:31:46 +0000509 while(((status = inw(EL_BASE_ADDR + VX_STATUS)) & S_COMMAND_IN_PROGRESS) != 0)
wdenkfe8c2802002-11-03 00:38:21 +0000510 {
511 udelay(10);
512 }
513 PRINTK(" ---> Tx completed, status = 0x%04x\n", status);
514
515 return length;
516}
517
518
wdenkfe8c2802002-11-03 00:38:21 +0000519#endif /* CONFIG_DRIVER_3C589 */