blob: 229658abc8eaedd5ca3d502b8677e942f960928c [file] [log] [blame]
wdenk45219c42003-05-12 21:50:16 +00001/*------------------------------------------------------------------------
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 *
Wolfgang Denk1a459662013-07-08 09:37:19 +020014 * SPDX-License-Identifier: GPL-2.0+
wdenk45219c42003-05-12 21:50:16 +000015 *
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 *
wdenk45219c42003-05-12 21:50:16 +000020 * "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:
Jean-Christophe PLAGNIOL-VILLARD1b769882008-01-25 07:54:47 +010026 * io = for the base address
wdenk45219c42003-05-12 21:50:16 +000027 * irq = for the IRQ
28 *
29 * author:
Jean-Christophe PLAGNIOL-VILLARD1b769882008-01-25 07:54:47 +010030 * Erik Stahlman ( erik@vt.edu )
31 * Daris A Nevil ( dnevil@snmc.com )
wdenk45219c42003-05-12 21:50:16 +000032 *
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:
Jean-Christophe PLAGNIOL-VILLARD1b769882008-01-25 07:54:47 +010043 * 04/30/03 Mathijs Haarman Modified smc91111.c (u-boot version)
wdenk45219c42003-05-12 21:50:16 +000044 * for lan91c96
45 *---------------------------------------------------------------------------
46 */
47
48#include <common.h>
49#include <command.h>
Nishanth Menonb7ad4102009-10-16 00:06:35 -050050#include <malloc.h>
wdenk45219c42003-05-12 21:50:16 +000051#include "lan91c96.h"
52#include <net.h>
Anatolij Gustschindffc0ae2011-11-19 13:12:12 +000053#include <linux/compiler.h>
wdenk45219c42003-05-12 21:50:16 +000054
wdenk45219c42003-05-12 21:50:16 +000055/*------------------------------------------------------------------------
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 */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500100#define DRIVER_NAME "LAN91C96"
wdenk45219c42003-05-12 21:50:16 +0000101#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
wdenk5ca26792004-06-06 22:11:41 +0000112/* 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*/
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500116static 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);
wdenk45219c42003-05-12 21:50:16 +0000118
wdenk45219c42003-05-12 21:50:16 +0000119/* ------------------------------------------------------------
120 * Internal routines
121 * ------------------------------------------------------------
122 */
123
Wolfgang Denkd52fb7e2006-03-11 22:53:33 +0100124static unsigned char smc_mac_addr[] = { 0xc0, 0x00, 0x00, 0x1b, 0x62, 0x9c };
wdenk45219c42003-05-12 21:50:16 +0000125
126/*
127 * This function must be called before smc_open() if you want to override
128 * the default mac address.
129 */
130
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500131static void smc_set_mac_addr(const unsigned char *addr)
wdenk45219c42003-05-12 21:50:16 +0000132{
133 int i;
134
135 for (i = 0; i < sizeof (smc_mac_addr); i++) {
136 smc_mac_addr[i] = addr[i];
137 }
138}
139
wdenk45219c42003-05-12 21:50:16 +0000140/***********************************************
141 * Show available memory *
142 ***********************************************/
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500143void dump_memory_info(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000144{
Anatolij Gustschindffc0ae2011-11-19 13:12:12 +0000145 __maybe_unused word mem_info;
wdenk45219c42003-05-12 21:50:16 +0000146 word old_bank;
147
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500148 old_bank = SMC_inw(dev, LAN91C96_BANK_SELECT) & 0xF;
wdenk45219c42003-05-12 21:50:16 +0000149
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500150 SMC_SELECT_BANK(dev, 0);
151 mem_info = SMC_inw(dev, LAN91C96_MIR);
wdenk45219c42003-05-12 21:50:16 +0000152 PRINTK2 ("Memory: %4d available\n", (mem_info >> 8) * 2048);
153
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500154 SMC_SELECT_BANK(dev, old_bank);
wdenk45219c42003-05-12 21:50:16 +0000155}
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
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500164static int poll4int (struct eth_device *dev, byte mask, int timeout)
wdenk45219c42003-05-12 21:50:16 +0000165{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200166 int tmo = get_timer (0) + timeout * CONFIG_SYS_HZ;
wdenk45219c42003-05-12 21:50:16 +0000167 int is_timeout = 0;
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500168 word old_bank = SMC_inw(dev, LAN91C96_BANK_SELECT);
wdenk45219c42003-05-12 21:50:16 +0000169
170 PRINTK2 ("Polling...\n");
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500171 SMC_SELECT_BANK(dev, 2);
172 while ((SMC_inw(dev, LAN91C96_INT_STATS) & mask) == 0) {
wdenk45219c42003-05-12 21:50:16 +0000173 if (get_timer (0) >= tmo) {
174 is_timeout = 1;
175 break;
176 }
177 }
178
179 /* restore old bank selection */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500180 SMC_SELECT_BANK(dev, old_bank);
wdenk45219c42003-05-12 21:50:16 +0000181
182 if (is_timeout)
183 return 1;
184 else
185 return 0;
186}
187
188/*
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500189 * Function: smc_reset
wdenk45219c42003-05-12 21:50:16 +0000190 * Purpose:
Jean-Christophe PLAGNIOL-VILLARD1b769882008-01-25 07:54:47 +0100191 * This sets the SMC91111 chip to its normal state, hopefully from whatever
192 * mess that any other DOS driver has put it in.
wdenk45219c42003-05-12 21:50:16 +0000193 *
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*/
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500205static void smc_reset(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000206{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500207 PRINTK2("%s:smc_reset\n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000208
209 /* This resets the registers mostly to defaults, but doesn't
210 affect EEPROM. That seems unnecessary */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500211 SMC_SELECT_BANK(dev, 0);
212 SMC_outw(dev, LAN91C96_RCR_SOFT_RST, LAN91C96_RCR);
wdenk45219c42003-05-12 21:50:16 +0000213
214 udelay (10);
215
216 /* Disable transmit and receive functionality */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500217 SMC_outw(dev, 0, LAN91C96_RCR);
218 SMC_outw(dev, 0, LAN91C96_TCR);
wdenk45219c42003-05-12 21:50:16 +0000219
220 /* set the control register */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500221 SMC_SELECT_BANK(dev, 1);
222 SMC_outw(dev, SMC_inw(dev, LAN91C96_CONTROL) | LAN91C96_CTR_BIT_8,
wdenk45219c42003-05-12 21:50:16 +0000223 LAN91C96_CONTROL);
224
225 /* Disable all interrupts */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500226 SMC_outb(dev, 0, LAN91C96_INT_MASK);
wdenk45219c42003-05-12 21:50:16 +0000227}
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*/
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500237static void smc_enable(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000238{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500239 PRINTK2("%s:smc_enable\n", dev->name);
240 SMC_SELECT_BANK(dev, 0);
wdenk45219c42003-05-12 21:50:16 +0000241
242 /* Initialize the Memory Configuration Register. See page
243 49 of the LAN91C96 data sheet for details. */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500244 SMC_outw(dev, LAN91C96_MCR_TRANSMIT_PAGES, LAN91C96_MCR);
wdenk45219c42003-05-12 21:50:16 +0000245
246 /* Initialize the Transmit Control Register */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500247 SMC_outw(dev, LAN91C96_TCR_TXENA, LAN91C96_TCR);
wdenk45219c42003-05-12 21:50:16 +0000248 /* 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 */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500254 SMC_outw(dev, LAN91C96_RCR_RXEN | LAN91C96_RCR_PRMS, LAN91C96_RCR);
wdenk45219c42003-05-12 21:50:16 +0000255}
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 */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500271static void smc_shutdown(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000272{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500273 PRINTK2("%s:smc_shutdown\n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000274
275 /* no more interrupts for me */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500276 SMC_SELECT_BANK(dev, 2);
277 SMC_outb(dev, 0, LAN91C96_INT_MASK);
wdenk45219c42003-05-12 21:50:16 +0000278
279 /* and tell the card to stay away from that nasty outside world */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500280 SMC_SELECT_BANK(dev, 0);
281 SMC_outb(dev, 0, LAN91C96_RCR);
282 SMC_outb(dev, 0, LAN91C96_TCR);
wdenk45219c42003-05-12 21:50:16 +0000283}
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:
Jean-Christophe PLAGNIOL-VILLARD1b769882008-01-25 07:54:47 +0100292 * First, see if a saved_skb is available.
wdenk45219c42003-05-12 21:50:16 +0000293 * ( 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
Jean-Christophe PLAGNIOL-VILLARD1b769882008-01-25 07:54:47 +0100300 * Tell the card to send it
wdenk45219c42003-05-12 21:50:16 +0000301 * Enable the transmit interrupt, so I know if it failed
Jean-Christophe PLAGNIOL-VILLARD1b769882008-01-25 07:54:47 +0100302 * Free the kernel data if I actually sent it.
wdenk45219c42003-05-12 21:50:16 +0000303 */
Joe Hershberger30934b32012-05-21 14:45:30 +0000304static int smc_send_packet(struct eth_device *dev, void *packet,
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500305 int packet_length)
wdenk45219c42003-05-12 21:50:16 +0000306{
307 byte packet_no;
wdenk45219c42003-05-12 21:50:16 +0000308 byte *buf;
309 int length;
310 int numPages;
311 int try = 0;
312 int time_out;
313 byte status;
314
315
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500316 PRINTK3("%s:smc_hardware_send_packet\n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000317
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) {
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500336 printf("%s: Far too big packet error. \n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000337 return 0;
338 }
339
340 /* now, try to allocate the memory */
341
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500342 SMC_SELECT_BANK(dev, 2);
343 SMC_outw(dev, LAN91C96_MMUCR_ALLOC_TX | numPages, LAN91C96_MMU);
wdenk45219c42003-05-12 21:50:16 +0000344
345 again:
346 try++;
347 time_out = MEMORY_WAIT_TIME;
348 do {
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500349 status = SMC_inb(dev, LAN91C96_INT_STATS);
wdenk45219c42003-05-12 21:50:16 +0000350 if (status & LAN91C96_IST_ALLOC_INT) {
351
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500352 SMC_outb(dev, LAN91C96_IST_ALLOC_INT,
353 LAN91C96_INT_STATS);
wdenk45219c42003-05-12 21:50:16 +0000354 break;
355 }
356 } while (--time_out);
357
358 if (!time_out) {
359 PRINTK2 ("%s: memory allocation, try %d failed ...\n",
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500360 dev->name, try);
wdenk45219c42003-05-12 21:50:16 +0000361 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",
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500368 dev->name, try);
wdenk45219c42003-05-12 21:50:16 +0000369
370 /* I can send the packet now.. */
wdenk45219c42003-05-12 21:50:16 +0000371 buf = (byte *) packet;
372
373 /* If I get here, I _know_ there is a packet slot waiting for me */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500374 packet_no = SMC_inb(dev, LAN91C96_ARR);
wdenk45219c42003-05-12 21:50:16 +0000375 if (packet_no & LAN91C96_ARR_FAILED) {
376 /* or isn't there? BAD CHIP! */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500377 printf("%s: Memory allocation failed. \n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000378 return 0;
379 }
380
381 /* we have a packet address, so tell the card to use it */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500382 SMC_outb(dev, packet_no, LAN91C96_PNR);
wdenk45219c42003-05-12 21:50:16 +0000383
384 /* point to the beginning of the packet */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500385 SMC_outw(dev, LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER);
wdenk45219c42003-05-12 21:50:16 +0000386
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500387 PRINTK3("%s: Trying to xmit packet of length %x\n",
388 dev->name, length);
wdenk45219c42003-05-12 21:50:16 +0000389
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
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500398 SMC_outl(dev, (length + 6) << 16, LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000399#else
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500400 SMC_outw(dev, 0, LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000401 /* send the packet length ( +6 for status words, length, and ctl */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500402 SMC_outw(dev, (length + 6), LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000403#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
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500413 SMC_outsl(dev, LAN91C96_DATA_HIGH, buf, length >> 2);
wdenk45219c42003-05-12 21:50:16 +0000414 if (length & 0x2)
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500415 SMC_outw(dev, *((word *) (buf + (length & 0xFFFFFFFC))),
wdenk45219c42003-05-12 21:50:16 +0000416 LAN91C96_DATA_HIGH);
417#else
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500418 SMC_outsw(dev, LAN91C96_DATA_HIGH, buf, (length) >> 1);
wdenk45219c42003-05-12 21:50:16 +0000419#endif /* USE_32_BIT */
420
421 /* Send the last byte, if there is one. */
422 if ((length & 1) == 0) {
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500423 SMC_outw(dev, 0, LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000424 } else {
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500425 SMC_outw(dev, buf[length - 1] | 0x2000, LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000426 }
427
428 /* and let the chipset deal with it */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500429 SMC_outw(dev, LAN91C96_MMUCR_ENQUEUE, LAN91C96_MMU);
wdenk45219c42003-05-12 21:50:16 +0000430
431 /* poll for TX INT */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500432 if (poll4int (dev, LAN91C96_MSK_TX_INT, SMC_TX_TIMEOUT)) {
wdenk45219c42003-05-12 21:50:16 +0000433 /* sending failed */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500434 PRINTK2("%s: TX timeout, sending failed...\n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000435
436 /* release packet */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500437 SMC_outw(dev, LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU);
wdenk45219c42003-05-12 21:50:16 +0000438
439 /* wait for MMU getting ready (low) */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500440 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
wdenk45219c42003-05-12 21:50:16 +0000441 udelay (10);
wdenk45219c42003-05-12 21:50:16 +0000442
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500443 PRINTK2("MMU ready\n");
wdenk45219c42003-05-12 21:50:16 +0000444
445
446 return 0;
447 } else {
448 /* ack. int */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500449 SMC_outw(dev, LAN91C96_IST_TX_INT, LAN91C96_INT_STATS);
wdenk45219c42003-05-12 21:50:16 +0000450
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500451 PRINTK2("%s: Sent packet of length %d \n", dev->name, length);
wdenk45219c42003-05-12 21:50:16 +0000452
453 /* release packet */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500454 SMC_outw(dev, LAN91C96_MMUCR_RELEASE_TX, LAN91C96_MMU);
wdenk45219c42003-05-12 21:50:16 +0000455
456 /* wait for MMU getting ready (low) */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500457 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
wdenk45219c42003-05-12 21:50:16 +0000458 udelay (10);
wdenk45219c42003-05-12 21:50:16 +0000459
460 PRINTK2 ("MMU ready\n");
461 }
462
463 return length;
464}
465
wdenk45219c42003-05-12 21:50:16 +0000466
467/*
468 * Open and Initialize the board
469 *
470 * Set up everything, reset the card, etc ..
471 *
472 */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500473static int smc_open(bd_t *bd, struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000474{
wdenk5ca26792004-06-06 22:11:41 +0000475 int i, err; /* used to set hw ethernet address */
wdenk45219c42003-05-12 21:50:16 +0000476
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500477 PRINTK2("%s:smc_open\n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000478
479 /* reset the hardware */
480
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500481 smc_reset(dev);
482 smc_enable(dev);
wdenk45219c42003-05-12 21:50:16 +0000483
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500484 SMC_SELECT_BANK(dev, 1);
485 /* set smc_mac_addr, and sync it with u-boot globals */
486 err = smc_get_ethaddr(bd, dev);
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500487 if (err < 0)
488 return -1;
wdenk5ca26792004-06-06 22:11:41 +0000489#ifdef USE_32_BIT
wdenk45219c42003-05-12 21:50:16 +0000490 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];
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500495 SMC_outw(dev, address, LAN91C96_IA0 + i);
wdenk45219c42003-05-12 21:50:16 +0000496 }
wdenka56bd922004-06-06 23:13:55 +0000497#else
wdenk5ca26792004-06-06 22:11:41 +0000498 for (i = 0; i < 6; i++)
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500499 SMC_outb(dev, smc_mac_addr[i], LAN91C96_IA0 + i);
wdenk5ca26792004-06-06 22:11:41 +0000500#endif
wdenk45219c42003-05-12 21:50:16 +0000501 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 */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500516static int smc_rcv(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000517{
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
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500528 SMC_SELECT_BANK(dev, 2);
529 packet_number = SMC_inw(dev, LAN91C96_FIFO);
wdenk45219c42003-05-12 21:50:16 +0000530
531 if (packet_number & LAN91C96_FIFO_RXEMPTY) {
532 return 0;
533 }
534
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500535 PRINTK3("%s:smc_rcv\n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000536 /* start reading from the start of the packet */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500537 SMC_outw(dev, LAN91C96_PTR_READ | LAN91C96_PTR_RCV |
wdenk45219c42003-05-12 21:50:16 +0000538 LAN91C96_PTR_AUTO_INCR, LAN91C96_POINTER);
539
540 /* First two words are status and packet_length */
541#ifdef USE_32_BIT
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500542 stat_len = SMC_inl(dev, LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000543 status = stat_len & 0xffff;
544 packet_length = stat_len >> 16;
545#else
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500546 status = SMC_inw(dev, LAN91C96_DATA_HIGH);
547 packet_length = SMC_inw(dev, LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000548#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
wdenk45219c42003-05-12 21:50:16 +0000559 /* 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 */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500571 SMC_insl(dev, LAN91C96_DATA_HIGH, NetRxPackets[0],
572 packet_length >> 2);
wdenk45219c42003-05-12 21:50:16 +0000573 /* read the left over bytes */
574 if (packet_length & 3) {
575 int i;
576
577 byte *tail = (byte *) (NetRxPackets[0] + (packet_length & ~3));
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500578 dword leftover = SMC_inl(dev, LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000579
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);
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500586 SMC_insw(dev, LAN91C96_DATA_HIGH, NetRxPackets[0],
587 packet_length >> 1);
wdenk45219c42003-05-12 21:50:16 +0000588
589#endif /* USE_32_BIT */
590
591#if SMC_DEBUG > 2
592 printf ("Receiving Packet\n");
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500593 print_packet((byte *)NetRxPackets[0], packet_length);
wdenk45219c42003-05-12 21:50:16 +0000594#endif
595 } else {
596 /* error ... */
597 /* TODO ? */
598 is_error = 1;
599 }
600
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500601 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
wdenk45219c42003-05-12 21:50:16 +0000602 udelay (1); /* Wait until not busy */
603
604 /* error or good, tell the card to get rid of this packet */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500605 SMC_outw(dev, LAN91C96_MMUCR_RELEASE_RX, LAN91C96_MMU);
wdenk45219c42003-05-12 21:50:16 +0000606
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500607 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
wdenk45219c42003-05-12 21:50:16 +0000608 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 -----------------------------------------------------*/
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500628static int smc_close(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000629{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500630 PRINTK2("%s:smc_close\n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000631
632 /* clear everything */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500633 smc_shutdown(dev);
wdenk45219c42003-05-12 21:50:16 +0000634
635 return 0;
636}
637
638#if SMC_DEBUG > 2
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500639static void print_packet(byte *buf, int length)
wdenk45219c42003-05-12 21:50:16 +0000640{
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
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500675static int lan91c96_init(struct eth_device *dev, bd_t *bd)
wdenk45219c42003-05-12 21:50:16 +0000676{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500677 return smc_open(bd, dev);
wdenk45219c42003-05-12 21:50:16 +0000678}
679
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500680static void lan91c96_halt(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000681{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500682 smc_close(dev);
wdenk45219c42003-05-12 21:50:16 +0000683}
684
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500685static int lan91c96_recv(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000686{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500687 return smc_rcv(dev);
wdenk45219c42003-05-12 21:50:16 +0000688}
689
Joe Hershberger30934b32012-05-21 14:45:30 +0000690static int lan91c96_send(struct eth_device *dev, void *packet,
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500691 int length)
wdenk45219c42003-05-12 21:50:16 +0000692{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500693 return smc_send_packet(dev, packet, length);
wdenk45219c42003-05-12 21:50:16 +0000694}
695
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500696/* smc_get_ethaddr
wdenk5ca26792004-06-06 22:11:41 +0000697 *
698 * This checks both the environment and the ROM for an ethernet address. If
699 * found, the environment takes precedence.
700 */
701
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500702static int smc_get_ethaddr(bd_t *bd, struct eth_device *dev)
wdenk5ca26792004-06-06 22:11:41 +0000703{
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500704 uchar v_mac[6];
wdenk5ca26792004-06-06 22:11:41 +0000705
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500706 if (!eth_getenv_enetaddr("ethaddr", v_mac)) {
707 /* get ROM mac value if any */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500708 if (!get_rom_mac(dev, v_mac)) {
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500709 printf("\n*** ERROR: ethaddr is NOT set !!\n");
710 return -1;
wdenk5ca26792004-06-06 22:11:41 +0000711 }
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500712 eth_setenv_enetaddr("ethaddr", v_mac);
wdenk5ca26792004-06-06 22:11:41 +0000713 }
714
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500715 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;
wdenk5ca26792004-06-06 22:11:41 +0000718}
719
wdenka56bd922004-06-06 23:13:55 +0000720/*
wdenk5ca26792004-06-06 22:11:41 +0000721 * get_rom_mac()
722 * Note, this has omly been tested for the OMAP730 P2.
723 */
724
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500725static int get_rom_mac(struct eth_device *dev, unsigned char *v_rom_mac)
wdenk5ca26792004-06-06 22:11:41 +0000726{
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;
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500734 SMC_SELECT_BANK(dev, 1);
wdenk5ca26792004-06-06 22:11:41 +0000735 for (i=0; i<6; i++)
736 {
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500737 v_rom_mac[i] = SMC_inb(dev, LAN91C96_IA0 + i);
wdenk5ca26792004-06-06 22:11:41 +0000738 }
739 return (1);
740#endif
741}
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500742
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"},
Yanjun Yang0e7790d2010-12-26 10:40:54 +0800754 {4, "LAN91C94/96"},
755 {3, "LAN91C90/92"},
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500756};
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);
Yanjun Yang16721712010-12-28 16:08:25 +0800767 chip_id = (SMC_inw(dev, 0xA) & LAN91C96_REV_CHIPID) >> 4;
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500768 SMC_SELECT_BANK(dev, 0);
Axel Lina62cd292013-07-03 11:24:18 +0800769 for (r = 0; r < ARRAY_SIZE(supported_chips); r++)
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500770 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) {
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500782 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}