]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/net/lan91c96.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[people/ms/u-boot.git] / drivers / net / lan91c96.c
CommitLineData
45219c46
WD
1/*------------------------------------------------------------------------
2 * lan91c96.c
3 * This is a driver for SMSC's LAN91C96 single-chip Ethernet device, based
4 * on the SMC91111 driver from U-boot.
5 *
6 * (C) Copyright 2002
7 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
8 * Rolf Offermanns <rof@sysgo.de>
9 *
10 * Copyright (C) 2001 Standard Microsystems Corporation (SMSC)
11 * Developed by Simple Network Magic Corporation (SNMC)
12 * Copyright (C) 1996 by Erik Stahlman (ES)
13 *
1a459660 14 * SPDX-License-Identifier: GPL-2.0+
45219c46
WD
15 *
16 * Information contained in this file was obtained from the LAN91C96
17 * manual from SMC. To get a copy, if you really want one, you can find
18 * information under www.smsc.com.
19 *
45219c46
WD
20 * "Features" of the SMC chip:
21 * 6144 byte packet memory. ( for the 91C96 )
22 * EEPROM for configuration
23 * AUI/TP selection ( mine has 10Base2/10BaseT select )
24 *
25 * Arguments:
1b769881 26 * io = for the base address
45219c46
WD
27 * irq = for the IRQ
28 *
29 * author:
1b769881
JCPV
30 * Erik Stahlman ( erik@vt.edu )
31 * Daris A Nevil ( dnevil@snmc.com )
45219c46
WD
32 *
33 *
34 * Hardware multicast code from Peter Cammaert ( pc@denkart.be )
35 *
36 * Sources:
37 * o SMSC LAN91C96 databook (www.smsc.com)
38 * o smc91111.c (u-boot driver)
39 * o smc9194.c (linux kernel driver)
40 * o lan91c96.c (Intel Diagnostic Manager driver)
41 *
42 * History:
1b769881 43 * 04/30/03 Mathijs Haarman Modified smc91111.c (u-boot version)
45219c46
WD
44 * for lan91c96
45 *---------------------------------------------------------------------------
46 */
47
48#include <common.h>
49#include <command.h>
b7ad4109 50#include <malloc.h>
45219c46
WD
51#include "lan91c96.h"
52#include <net.h>
dffc0ae8 53#include <linux/compiler.h>
45219c46 54
45219c46
WD
55/*------------------------------------------------------------------------
56 *
57 * Configuration options, for the experienced user to change.
58 *
59 -------------------------------------------------------------------------*/
60
61/* Use power-down feature of the chip */
62#define POWER_DOWN 0
63
64/*
65 * Wait time for memory to be free. This probably shouldn't be
66 * tuned that much, as waiting for this means nothing else happens
67 * in the system
68*/
69#define MEMORY_WAIT_TIME 16
70
71#define SMC_DEBUG 0
72
73#if (SMC_DEBUG > 2 )
74#define PRINTK3(args...) printf(args)
75#else
76#define PRINTK3(args...)
77#endif
78
79#if SMC_DEBUG > 1
80#define PRINTK2(args...) printf(args)
81#else
82#define PRINTK2(args...)
83#endif
84
85#ifdef SMC_DEBUG
86#define PRINTK(args...) printf(args)
87#else
88#define PRINTK(args...)
89#endif
90
91
92/*------------------------------------------------------------------------
93 *
94 * The internal workings of the driver. If you are changing anything
95 * here with the SMC stuff, you should have the datasheet and know
96 * what you are doing.
97 *
98 *------------------------------------------------------------------------
99 */
b7ad4109 100#define DRIVER_NAME "LAN91C96"
45219c46
WD
101#define SMC_ALLOC_MAX_TRY 5
102#define SMC_TX_TIMEOUT 30
103
104#define ETH_ZLEN 60
105
106#ifdef CONFIG_LAN91C96_USE_32_BIT
107#define USE_32_BIT 1
108#else
109#undef USE_32_BIT
110#endif
111
5ca26799
WD
112/* See if a MAC address is defined in the current environment. If so use it. If not
113 . print a warning and set the environment and other globals with the default.
114 . If an EEPROM is present it really should be consulted.
115*/
b7ad4109
NM
116static int smc_get_ethaddr(bd_t *bd, struct eth_device *dev);
117static int get_rom_mac(struct eth_device *dev, unsigned char *v_rom_mac);
45219c46 118
45219c46
WD
119/* ------------------------------------------------------------
120 * Internal routines
121 * ------------------------------------------------------------
122 */
123
d52fb7e3 124static unsigned char smc_mac_addr[] = { 0xc0, 0x00, 0x00, 0x1b, 0x62, 0x9c };
45219c46
WD
125
126/*
127 * This function must be called before smc_open() if you want to override
128 * the default mac address.
129 */
130
b7ad4109 131static void smc_set_mac_addr(const unsigned char *addr)
45219c46
WD
132{
133 int i;
134
135 for (i = 0; i < sizeof (smc_mac_addr); i++) {
136 smc_mac_addr[i] = addr[i];
137 }
138}
139
45219c46
WD
140/***********************************************
141 * Show available memory *
142 ***********************************************/
b7ad4109 143void dump_memory_info(struct eth_device *dev)
45219c46 144{
dffc0ae8 145 __maybe_unused word mem_info;
45219c46
WD
146 word old_bank;
147
b7ad4109 148 old_bank = SMC_inw(dev, LAN91C96_BANK_SELECT) & 0xF;
45219c46 149
b7ad4109
NM
150 SMC_SELECT_BANK(dev, 0);
151 mem_info = SMC_inw(dev, LAN91C96_MIR);
45219c46
WD
152 PRINTK2 ("Memory: %4d available\n", (mem_info >> 8) * 2048);
153
b7ad4109 154 SMC_SELECT_BANK(dev, old_bank);
45219c46
WD
155}
156
157/*
158 * A rather simple routine to print out a packet for debugging purposes.
159 */
160#if SMC_DEBUG > 2
161static void print_packet (byte *, int);
162#endif
163
b7ad4109 164static int poll4int (struct eth_device *dev, byte mask, int timeout)
45219c46 165{
6d0f6bcf 166 int tmo = get_timer (0) + timeout * CONFIG_SYS_HZ;
45219c46 167 int is_timeout = 0;
b7ad4109 168 word old_bank = SMC_inw(dev, LAN91C96_BANK_SELECT);
45219c46
WD
169
170 PRINTK2 ("Polling...\n");
b7ad4109
NM
171 SMC_SELECT_BANK(dev, 2);
172 while ((SMC_inw(dev, LAN91C96_INT_STATS) & mask) == 0) {
45219c46
WD
173 if (get_timer (0) >= tmo) {
174 is_timeout = 1;
175 break;
176 }
177 }
178
179 /* restore old bank selection */
b7ad4109 180 SMC_SELECT_BANK(dev, old_bank);
45219c46
WD
181
182 if (is_timeout)
183 return 1;
184 else
185 return 0;
186}
187
188/*
b7ad4109 189 * Function: smc_reset
45219c46 190 * Purpose:
1b769881
JCPV
191 * This sets the SMC91111 chip to its normal state, hopefully from whatever
192 * mess that any other DOS driver has put it in.
45219c46
WD
193 *
194 * Maybe I should reset more registers to defaults in here? SOFTRST should
195 * do that for me.
196 *
197 * Method:
198 * 1. send a SOFT RESET
199 * 2. wait for it to finish
200 * 3. enable autorelease mode
201 * 4. reset the memory management unit
202 * 5. clear all interrupts
203 *
204*/
b7ad4109 205static void smc_reset(struct eth_device *dev)
45219c46 206{
b7ad4109 207 PRINTK2("%s:smc_reset\n", dev->name);
45219c46
WD
208
209 /* This resets the registers mostly to defaults, but doesn't
210 affect EEPROM. That seems unnecessary */
b7ad4109
NM
211 SMC_SELECT_BANK(dev, 0);
212 SMC_outw(dev, LAN91C96_RCR_SOFT_RST, LAN91C96_RCR);
45219c46
WD
213
214 udelay (10);
215
216 /* Disable transmit and receive functionality */
b7ad4109
NM
217 SMC_outw(dev, 0, LAN91C96_RCR);
218 SMC_outw(dev, 0, LAN91C96_TCR);
45219c46
WD
219
220 /* set the control register */
b7ad4109
NM
221 SMC_SELECT_BANK(dev, 1);
222 SMC_outw(dev, SMC_inw(dev, LAN91C96_CONTROL) | LAN91C96_CTR_BIT_8,
45219c46
WD
223 LAN91C96_CONTROL);
224
225 /* Disable all interrupts */
b7ad4109 226 SMC_outb(dev, 0, LAN91C96_INT_MASK);
45219c46
WD
227}
228
229/*
230 * Function: smc_enable
231 * Purpose: let the chip talk to the outside work
232 * Method:
233 * 1. Initialize the Memory Configuration Register
234 * 2. Enable the transmitter
235 * 3. Enable the receiver
236*/
b7ad4109 237static void smc_enable(struct eth_device *dev)
45219c46 238{
b7ad4109
NM
239 PRINTK2("%s:smc_enable\n", dev->name);
240 SMC_SELECT_BANK(dev, 0);
45219c46
WD
241
242 /* Initialize the Memory Configuration Register. See page
243 49 of the LAN91C96 data sheet for details. */
b7ad4109 244 SMC_outw(dev, LAN91C96_MCR_TRANSMIT_PAGES, LAN91C96_MCR);
45219c46
WD
245
246 /* Initialize the Transmit Control Register */
b7ad4109 247 SMC_outw(dev, LAN91C96_TCR_TXENA, LAN91C96_TCR);
45219c46
WD
248 /* Initialize the Receive Control Register
249 * FIXME:
250 * The promiscuous bit set because I could not receive ARP reply
251 * packets from the server when I send a ARP request. It only works
252 * when I set the promiscuous bit
253 */
b7ad4109 254 SMC_outw(dev, LAN91C96_RCR_RXEN | LAN91C96_RCR_PRMS, LAN91C96_RCR);
45219c46
WD
255}
256
257/*
258 * Function: smc_shutdown
259 * Purpose: closes down the SMC91xxx chip.
260 * Method:
261 * 1. zero the interrupt mask
262 * 2. clear the enable receive flag
263 * 3. clear the enable xmit flags
264 *
265 * TODO:
266 * (1) maybe utilize power down mode.
267 * Why not yet? Because while the chip will go into power down mode,
268 * the manual says that it will wake up in response to any I/O requests
269 * in the register space. Empirical results do not show this working.
270 */
b7ad4109 271static void smc_shutdown(struct eth_device *dev)
45219c46 272{
b7ad4109 273 PRINTK2("%s:smc_shutdown\n", dev->name);
45219c46
WD
274
275 /* no more interrupts for me */
b7ad4109
NM
276 SMC_SELECT_BANK(dev, 2);
277 SMC_outb(dev, 0, LAN91C96_INT_MASK);
45219c46
WD
278
279 /* and tell the card to stay away from that nasty outside world */
b7ad4109
NM
280 SMC_SELECT_BANK(dev, 0);
281 SMC_outb(dev, 0, LAN91C96_RCR);
282 SMC_outb(dev, 0, LAN91C96_TCR);
45219c46
WD
283}
284
285
286/*
287 * Function: smc_hardware_send_packet(struct net_device * )
288 * Purpose:
289 * This sends the actual packet to the SMC9xxx chip.
290 *
291 * Algorithm:
1b769881 292 * First, see if a saved_skb is available.
45219c46
WD
293 * ( this should NOT be called if there is no 'saved_skb'
294 * Now, find the packet number that the chip allocated
295 * Point the data pointers at it in memory
296 * Set the length word in the chip's memory
297 * Dump the packet to chip memory
298 * Check if a last byte is needed ( odd length packet )
299 * if so, set the control flag right
1b769881 300 * Tell the card to send it
45219c46 301 * Enable the transmit interrupt, so I know if it failed
1b769881 302 * Free the kernel data if I actually sent it.
45219c46 303 */
30934b3e 304static int smc_send_packet(struct eth_device *dev, void *packet,
b7ad4109 305 int packet_length)
45219c46
WD
306{
307 byte packet_no;
45219c46
WD
308 byte *buf;
309 int length;
310 int numPages;
311 int try = 0;
312 int time_out;
313 byte status;
314
315
b7ad4109 316 PRINTK3("%s:smc_hardware_send_packet\n", dev->name);
45219c46
WD
317
318 length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN;
319
320 /* allocate memory
321 ** The MMU wants the number of pages to be the number of 256 bytes
322 ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
323 **
324 ** The 91C111 ignores the size bits, but the code is left intact
325 ** for backwards and future compatibility.
326 **
327 ** Pkt size for allocating is data length +6 (for additional status
328 ** words, length and ctl!)
329 **
330 ** If odd size then last byte is included in this header.
331 */
332 numPages = ((length & 0xfffe) + 6);
333 numPages >>= 8; /* Divide by 256 */
334
335 if (numPages > 7) {
b7ad4109 336 printf("%s: Far too big packet error. \n", dev->name);
45219c46
WD
337 return 0;
338 }
339
340 /* now, try to allocate the memory */
341
b7ad4109
NM
342 SMC_SELECT_BANK(dev, 2);
343 SMC_outw(dev, LAN91C96_MMUCR_ALLOC_TX | numPages, LAN91C96_MMU);
45219c46
WD
344
345 again:
346 try++;
347 time_out = MEMORY_WAIT_TIME;
348 do {
b7ad4109 349 status = SMC_inb(dev, LAN91C96_INT_STATS);
45219c46
WD
350 if (status & LAN91C96_IST_ALLOC_INT) {
351
b7ad4109
NM
352 SMC_outb(dev, LAN91C96_IST_ALLOC_INT,
353 LAN91C96_INT_STATS);
45219c46
WD
354 break;
355 }
356 } while (--time_out);
357
358 if (!time_out) {
359 PRINTK2 ("%s: memory allocation, try %d failed ...\n",
b7ad4109 360 dev->name, try);
45219c46
WD
361 if (try < SMC_ALLOC_MAX_TRY)
362 goto again;
363 else
364 return 0;
365 }
366
367 PRINTK2 ("%s: memory allocation, try %d succeeded ...\n",
b7ad4109 368 dev->name, try);
45219c46
WD
369
370 /* I can send the packet now.. */
45219c46
WD
371 buf = (byte *) packet;
372
373 /* If I get here, I _know_ there is a packet slot waiting for me */
b7ad4109 374 packet_no = SMC_inb(dev, LAN91C96_ARR);
45219c46
WD
375 if (packet_no & LAN91C96_ARR_FAILED) {
376 /* or isn't there? BAD CHIP! */
b7ad4109 377 printf("%s: Memory allocation failed. \n", dev->name);
45219c46
WD
378 return 0;
379 }
380
381 /* we have a packet address, so tell the card to use it */
b7ad4109 382 SMC_outb(dev, packet_no, LAN91C96_PNR);
45219c46
WD
383
384 /* point to the beginning of the packet */
b7ad4109 385 SMC_outw(dev, LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER);
45219c46 386
b7ad4109
NM
387 PRINTK3("%s: Trying to xmit packet of length %x\n",
388 dev->name, length);
45219c46
WD
389
390#if SMC_DEBUG > 2
391 printf ("Transmitting Packet\n");
392 print_packet (buf, length);
393#endif
394
395 /* send the packet length ( +6 for status, length and ctl byte )
396 and the status word ( set to zeros ) */
397#ifdef USE_32_BIT
b7ad4109 398 SMC_outl(dev, (length + 6) << 16, LAN91C96_DATA_HIGH);
45219c46 399#else
b7ad4109 400 SMC_outw(dev, 0, LAN91C96_DATA_HIGH);
45219c46 401 /* send the packet length ( +6 for status words, length, and ctl */
b7ad4109 402 SMC_outw(dev, (length + 6), LAN91C96_DATA_HIGH);
45219c46
WD
403#endif /* USE_32_BIT */
404
405 /* send the actual data
406 * I _think_ it's faster to send the longs first, and then
407 * mop up by sending the last word. It depends heavily
408 * on alignment, at least on the 486. Maybe it would be
409 * a good idea to check which is optimal? But that could take
410 * almost as much time as is saved?
411 */
412#ifdef USE_32_BIT
b7ad4109 413 SMC_outsl(dev, LAN91C96_DATA_HIGH, buf, length >> 2);
45219c46 414 if (length & 0x2)
b7ad4109 415 SMC_outw(dev, *((word *) (buf + (length & 0xFFFFFFFC))),
45219c46
WD
416 LAN91C96_DATA_HIGH);
417#else
b7ad4109 418 SMC_outsw(dev, LAN91C96_DATA_HIGH, buf, (length) >> 1);
45219c46
WD
419#endif /* USE_32_BIT */
420
421 /* Send the last byte, if there is one. */
422 if ((length & 1) == 0) {
b7ad4109 423 SMC_outw(dev, 0, LAN91C96_DATA_HIGH);
45219c46 424 } else {
b7ad4109 425 SMC_outw(dev, buf[length - 1] | 0x2000, LAN91C96_DATA_HIGH);
45219c46
WD
426 }
427
428 /* and let the chipset deal with it */
b7ad4109 429 SMC_outw(dev, LAN91C96_MMUCR_ENQUEUE, LAN91C96_MMU);
45219c46
WD
430
431 /* poll for TX INT */
b7ad4109 432 if (poll4int (dev, LAN91C96_MSK_TX_INT, SMC_TX_TIMEOUT)) {
45219c46 433 /* sending failed */
b7ad4109 434 PRINTK2("%s: TX timeout, sending failed...\n", dev->name);
45219c46
WD
435
436 /* release packet */
b7ad4109 437 SMC_outw(dev, LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU);
45219c46
WD
438
439 /* wait for MMU getting ready (low) */
b7ad4109 440 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
45219c46 441 udelay (10);
45219c46 442
b7ad4109 443 PRINTK2("MMU ready\n");
45219c46
WD
444
445
446 return 0;
447 } else {
448 /* ack. int */
b7ad4109 449 SMC_outw(dev, LAN91C96_IST_TX_INT, LAN91C96_INT_STATS);
45219c46 450
b7ad4109 451 PRINTK2("%s: Sent packet of length %d \n", dev->name, length);
45219c46
WD
452
453 /* release packet */
b7ad4109 454 SMC_outw(dev, LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU);
45219c46
WD
455
456 /* wait for MMU getting ready (low) */
b7ad4109 457 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
45219c46 458 udelay (10);
45219c46
WD
459
460 PRINTK2 ("MMU ready\n");
461 }
462
463 return length;
464}
465
45219c46
WD
466
467/*
468 * Open and Initialize the board
469 *
470 * Set up everything, reset the card, etc ..
471 *
472 */
b7ad4109 473static int smc_open(bd_t *bd, struct eth_device *dev)
45219c46 474{
5ca26799 475 int i, err; /* used to set hw ethernet address */
45219c46 476
b7ad4109 477 PRINTK2("%s:smc_open\n", dev->name);
45219c46
WD
478
479 /* reset the hardware */
480
b7ad4109
NM
481 smc_reset(dev);
482 smc_enable(dev);
45219c46 483
b7ad4109
NM
484 SMC_SELECT_BANK(dev, 1);
485 /* set smc_mac_addr, and sync it with u-boot globals */
486 err = smc_get_ethaddr(bd, dev);
03f3d8d3
MF
487 if (err < 0)
488 return -1;
5ca26799 489#ifdef USE_32_BIT
45219c46
WD
490 for (i = 0; i < 6; i += 2) {
491 word address;
492
493 address = smc_mac_addr[i + 1] << 8;
494 address |= smc_mac_addr[i];
b7ad4109 495 SMC_outw(dev, address, LAN91C96_IA0 + i);
45219c46 496 }
a56bd922 497#else
5ca26799 498 for (i = 0; i < 6; i++)
b7ad4109 499 SMC_outb(dev, smc_mac_addr[i], LAN91C96_IA0 + i);
5ca26799 500#endif
45219c46
WD
501 return 0;
502}
503
504/*-------------------------------------------------------------
505 *
506 * smc_rcv - receive a packet from the card
507 *
508 * There is ( at least ) a packet waiting to be read from
509 * chip-memory.
510 *
511 * o Read the status
512 * o If an error, record it
513 * o otherwise, read in the packet
514 *-------------------------------------------------------------
515 */
b7ad4109 516static int smc_rcv(struct eth_device *dev)
45219c46
WD
517{
518 int packet_number;
519 word status;
520 word packet_length;
521 int is_error = 0;
522
523#ifdef USE_32_BIT
524 dword stat_len;
525#endif
526
527
b7ad4109
NM
528 SMC_SELECT_BANK(dev, 2);
529 packet_number = SMC_inw(dev, LAN91C96_FIFO);
45219c46
WD
530
531 if (packet_number & LAN91C96_FIFO_RXEMPTY) {
532 return 0;
533 }
534
b7ad4109 535 PRINTK3("%s:smc_rcv\n", dev->name);
45219c46 536 /* start reading from the start of the packet */
b7ad4109 537 SMC_outw(dev, LAN91C96_PTR_READ | LAN91C96_PTR_RCV |
45219c46
WD
538 LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER);
539
540 /* First two words are status and packet_length */
541#ifdef USE_32_BIT
b7ad4109 542 stat_len = SMC_inl(dev, LAN91C96_DATA_HIGH);
45219c46
WD
543 status = stat_len & 0xffff;
544 packet_length = stat_len >> 16;
545#else
b7ad4109
NM
546 status = SMC_inw(dev, LAN91C96_DATA_HIGH);
547 packet_length = SMC_inw(dev, LAN91C96_DATA_HIGH);
45219c46
WD
548#endif
549
550 packet_length &= 0x07ff; /* mask off top bits */
551
552 PRINTK2 ("RCV: STATUS %4x LENGTH %4x\n", status, packet_length);
553
554 if (!(status & FRAME_FILTER)) {
555 /* Adjust for having already read the first two words */
556 packet_length -= 4; /*4; */
557
558
45219c46
WD
559 /* set odd length for bug in LAN91C111, */
560 /* which never sets RS_ODDFRAME */
561 /* TODO ? */
562
563
564#ifdef USE_32_BIT
565 PRINTK3 (" Reading %d dwords (and %d bytes) \n",
566 packet_length >> 2, packet_length & 3);
567 /* QUESTION: Like in the TX routine, do I want
568 to send the DWORDs or the bytes first, or some
569 mixture. A mixture might improve already slow PIO
570 performance */
b7ad4109
NM
571 SMC_insl(dev, LAN91C96_DATA_HIGH, NetRxPackets[0],
572 packet_length >> 2);
45219c46
WD
573 /* read the left over bytes */
574 if (packet_length & 3) {
575 int i;
576
577 byte *tail = (byte *) (NetRxPackets[0] + (packet_length & ~3));
b7ad4109 578 dword leftover = SMC_inl(dev, LAN91C96_DATA_HIGH);
45219c46
WD
579
580 for (i = 0; i < (packet_length & 3); i++)
581 *tail++ = (byte) (leftover >> (8 * i)) & 0xff;
582 }
583#else
584 PRINTK3 (" Reading %d words and %d byte(s) \n",
585 (packet_length >> 1), packet_length & 1);
b7ad4109
NM
586 SMC_insw(dev, LAN91C96_DATA_HIGH, NetRxPackets[0],
587 packet_length >> 1);
45219c46
WD
588
589#endif /* USE_32_BIT */
590
591#if SMC_DEBUG > 2
592 printf ("Receiving Packet\n");
b7ad4109 593 print_packet((byte *)NetRxPackets[0], packet_length);
45219c46
WD
594#endif
595 } else {
596 /* error ... */
597 /* TODO ? */
598 is_error = 1;
599 }
600
b7ad4109 601 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
45219c46
WD
602 udelay (1); /* Wait until not busy */
603
604 /* error or good, tell the card to get rid of this packet */
b7ad4109 605 SMC_outw(dev, LAN91C96_MMUCR_RELEASE_RX, LAN91C96_MMU);
45219c46 606
b7ad4109 607 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
45219c46
WD
608 udelay (1); /* Wait until not busy */
609
610 if (!is_error) {
611 /* Pass the packet up to the protocol layers. */
612 NetReceive (NetRxPackets[0], packet_length);
613 return packet_length;
614 } else {
615 return 0;
616 }
617
618}
619
620/*----------------------------------------------------
621 * smc_close
622 *
623 * this makes the board clean up everything that it can
624 * and not talk to the outside world. Caused by
625 * an 'ifconfig ethX down'
626 *
627 -----------------------------------------------------*/
b7ad4109 628static int smc_close(struct eth_device *dev)
45219c46 629{
b7ad4109 630 PRINTK2("%s:smc_close\n", dev->name);
45219c46
WD
631
632 /* clear everything */
b7ad4109 633 smc_shutdown(dev);
45219c46
WD
634
635 return 0;
636}
637
638#if SMC_DEBUG > 2
b7ad4109 639static void print_packet(byte *buf, int length)
45219c46
WD
640{
641#if 0
642 int i;
643 int remainder;
644 int lines;
645
646 printf ("Packet of length %d \n", length);
647
648 lines = length / 16;
649 remainder = length % 16;
650
651 for (i = 0; i < lines; i++) {
652 int cur;
653
654 for (cur = 0; cur < 8; cur++) {
655 byte a, b;
656
657 a = *(buf++);
658 b = *(buf++);
659 printf ("%02x%02x ", a, b);
660 }
661 printf ("\n");
662 }
663 for (i = 0; i < remainder / 2; i++) {
664 byte a, b;
665
666 a = *(buf++);
667 b = *(buf++);
668 printf ("%02x%02x ", a, b);
669 }
670 printf ("\n");
671#endif /* 0 */
672}
673#endif /* SMC_DEBUG > 2 */
674
b7ad4109 675static int lan91c96_init(struct eth_device *dev, bd_t *bd)
45219c46 676{
b7ad4109 677 return smc_open(bd, dev);
45219c46
WD
678}
679
b7ad4109 680static void lan91c96_halt(struct eth_device *dev)
45219c46 681{
b7ad4109 682 smc_close(dev);
45219c46
WD
683}
684
b7ad4109 685static int lan91c96_recv(struct eth_device *dev)
45219c46 686{
b7ad4109 687 return smc_rcv(dev);
45219c46
WD
688}
689
30934b3e 690static int lan91c96_send(struct eth_device *dev, void *packet,
b7ad4109 691 int length)
45219c46 692{
b7ad4109 693 return smc_send_packet(dev, packet, length);
45219c46
WD
694}
695
b7ad4109 696/* smc_get_ethaddr
5ca26799
WD
697 *
698 * This checks both the environment and the ROM for an ethernet address. If
699 * found, the environment takes precedence.
700 */
701
b7ad4109 702static int smc_get_ethaddr(bd_t *bd, struct eth_device *dev)
5ca26799 703{
03f3d8d3 704 uchar v_mac[6];
5ca26799 705
03f3d8d3
MF
706 if (!eth_getenv_enetaddr("ethaddr", v_mac)) {
707 /* get ROM mac value if any */
b7ad4109 708 if (!get_rom_mac(dev, v_mac)) {
03f3d8d3
MF
709 printf("\n*** ERROR: ethaddr is NOT set !!\n");
710 return -1;
5ca26799 711 }
03f3d8d3 712 eth_setenv_enetaddr("ethaddr", v_mac);
5ca26799
WD
713 }
714
03f3d8d3
MF
715 smc_set_mac_addr(v_mac); /* use old function to update smc default */
716 PRINTK("Using MAC Address %pM\n", v_mac);
717 return 0;
5ca26799
WD
718}
719
a56bd922 720/*
5ca26799
WD
721 * get_rom_mac()
722 * Note, this has omly been tested for the OMAP730 P2.
723 */
724
b7ad4109 725static int get_rom_mac(struct eth_device *dev, unsigned char *v_rom_mac)
5ca26799
WD
726{
727#ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */
728 char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 };
729
730 memcpy (v_rom_mac, hw_mac_addr, 6);
731 return (1);
732#else
733 int i;
b7ad4109 734 SMC_SELECT_BANK(dev, 1);
5ca26799
WD
735 for (i=0; i<6; i++)
736 {
b7ad4109 737 v_rom_mac[i] = SMC_inb(dev, LAN91C96_IA0 + i);
5ca26799
WD
738 }
739 return (1);
740#endif
741}
b7ad4109
NM
742
743/* Structure to detect the device IDs */
744struct id_type {
745 u8 id;
746 char *name;
747};
748static struct id_type supported_chips[] = {
749 {0, ""}, /* Dummy entry to prevent id check failure */
750 {9, "LAN91C110"},
751 {8, "LAN91C100FD"},
752 {7, "LAN91C100"},
753 {5, "LAN91C95"},
0e7790d4
YY
754 {4, "LAN91C94/96"},
755 {3, "LAN91C90/92"},
b7ad4109
NM
756};
757/* lan91c96_detect_chip
758 * See:
759 * http://www.embeddedsys.com/subpages/resources/images/documents/LAN91C96_datasheet.pdf
760 * page 71 - that is the closest we get to detect this device
761 */
762static int lan91c96_detect_chip(struct eth_device *dev)
763{
764 u8 chip_id;
765 int r;
766 SMC_SELECT_BANK(dev, 3);
16721715 767 chip_id = (SMC_inw(dev, 0xA) & LAN91C96_REV_CHIPID) >> 4;
b7ad4109
NM
768 SMC_SELECT_BANK(dev, 0);
769 for (r = 0; r < sizeof(supported_chips) / sizeof(struct id_type); r++)
770 if (chip_id == supported_chips[r].id)
771 return r;
772 return 0;
773}
774
775int lan91c96_initialize(u8 dev_num, int base_addr)
776{
777 struct eth_device *dev;
778 int r = 0;
779
780 dev = malloc(sizeof(*dev));
781 if (!dev) {
b7ad4109
NM
782 return 0;
783 }
784 memset(dev, 0, sizeof(*dev));
785
786 dev->iobase = base_addr;
787
788 /* Try to detect chip. Will fail if not present. */
789 r = lan91c96_detect_chip(dev);
790 if (!r) {
791 free(dev);
792 return 0;
793 }
794 get_rom_mac(dev, dev->enetaddr);
795
796 dev->init = lan91c96_init;
797 dev->halt = lan91c96_halt;
798 dev->send = lan91c96_send;
799 dev->recv = lan91c96_recv;
800 sprintf(dev->name, "%s-%hu", supported_chips[r].name, dev_num);
801
802 eth_register(dev);
803 return 0;
804}