blob: 3526876d1419cfb2bd2660f190306d90aa0798bf [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
Bin Menga1875592016-02-05 19:30:11 -08004 * on the SMC91111 driver from U-Boot.
wdenk45219c42003-05-12 21:50:16 +00005 *
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 */
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500571 SMC_insl(dev, LAN91C96_DATA_HIGH, net_rx_packets[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
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500577 byte *tail = (byte *)(net_rx_packets[0] +
578 (packet_length & ~3));
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500579 dword leftover = SMC_inl(dev, LAN91C96_DATA_HIGH);
wdenk45219c42003-05-12 21:50:16 +0000580
581 for (i = 0; i < (packet_length & 3); i++)
582 *tail++ = (byte) (leftover >> (8 * i)) & 0xff;
583 }
584#else
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500585 PRINTK3(" Reading %d words and %d byte(s)\n",
586 (packet_length >> 1), packet_length & 1);
587 SMC_insw(dev, LAN91C96_DATA_HIGH, net_rx_packets[0],
588 packet_length >> 1);
wdenk45219c42003-05-12 21:50:16 +0000589
590#endif /* USE_32_BIT */
591
592#if SMC_DEBUG > 2
593 printf ("Receiving Packet\n");
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500594 print_packet((byte *)net_rx_packets[0], packet_length);
wdenk45219c42003-05-12 21:50:16 +0000595#endif
596 } else {
597 /* error ... */
598 /* TODO ? */
599 is_error = 1;
600 }
601
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500602 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
wdenk45219c42003-05-12 21:50:16 +0000603 udelay (1); /* Wait until not busy */
604
605 /* error or good, tell the card to get rid of this packet */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500606 SMC_outw(dev, LAN91C96_MMUCR_RELEASE_RX, LAN91C96_MMU);
wdenk45219c42003-05-12 21:50:16 +0000607
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500608 while (SMC_inw(dev, LAN91C96_MMU) & LAN91C96_MMUCR_NO_BUSY)
wdenk45219c42003-05-12 21:50:16 +0000609 udelay (1); /* Wait until not busy */
610
611 if (!is_error) {
612 /* Pass the packet up to the protocol layers. */
Joe Hershberger1fd92db2015-04-08 01:41:06 -0500613 net_process_received_packet(net_rx_packets[0], packet_length);
wdenk45219c42003-05-12 21:50:16 +0000614 return packet_length;
615 } else {
616 return 0;
617 }
618
619}
620
621/*----------------------------------------------------
622 * smc_close
623 *
624 * this makes the board clean up everything that it can
625 * and not talk to the outside world. Caused by
626 * an 'ifconfig ethX down'
627 *
628 -----------------------------------------------------*/
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500629static int smc_close(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000630{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500631 PRINTK2("%s:smc_close\n", dev->name);
wdenk45219c42003-05-12 21:50:16 +0000632
633 /* clear everything */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500634 smc_shutdown(dev);
wdenk45219c42003-05-12 21:50:16 +0000635
636 return 0;
637}
638
639#if SMC_DEBUG > 2
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500640static void print_packet(byte *buf, int length)
wdenk45219c42003-05-12 21:50:16 +0000641{
642#if 0
643 int i;
644 int remainder;
645 int lines;
646
647 printf ("Packet of length %d \n", length);
648
649 lines = length / 16;
650 remainder = length % 16;
651
652 for (i = 0; i < lines; i++) {
653 int cur;
654
655 for (cur = 0; cur < 8; cur++) {
656 byte a, b;
657
658 a = *(buf++);
659 b = *(buf++);
660 printf ("%02x%02x ", a, b);
661 }
662 printf ("\n");
663 }
664 for (i = 0; i < remainder / 2; i++) {
665 byte a, b;
666
667 a = *(buf++);
668 b = *(buf++);
669 printf ("%02x%02x ", a, b);
670 }
671 printf ("\n");
672#endif /* 0 */
673}
674#endif /* SMC_DEBUG > 2 */
675
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500676static int lan91c96_init(struct eth_device *dev, bd_t *bd)
wdenk45219c42003-05-12 21:50:16 +0000677{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500678 return smc_open(bd, dev);
wdenk45219c42003-05-12 21:50:16 +0000679}
680
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500681static void lan91c96_halt(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000682{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500683 smc_close(dev);
wdenk45219c42003-05-12 21:50:16 +0000684}
685
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500686static int lan91c96_recv(struct eth_device *dev)
wdenk45219c42003-05-12 21:50:16 +0000687{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500688 return smc_rcv(dev);
wdenk45219c42003-05-12 21:50:16 +0000689}
690
Joe Hershberger30934b32012-05-21 14:45:30 +0000691static int lan91c96_send(struct eth_device *dev, void *packet,
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500692 int length)
wdenk45219c42003-05-12 21:50:16 +0000693{
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500694 return smc_send_packet(dev, packet, length);
wdenk45219c42003-05-12 21:50:16 +0000695}
696
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500697/* smc_get_ethaddr
wdenk5ca26792004-06-06 22:11:41 +0000698 *
699 * This checks both the environment and the ROM for an ethernet address. If
700 * found, the environment takes precedence.
701 */
702
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500703static int smc_get_ethaddr(bd_t *bd, struct eth_device *dev)
wdenk5ca26792004-06-06 22:11:41 +0000704{
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500705 uchar v_mac[6];
wdenk5ca26792004-06-06 22:11:41 +0000706
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500707 if (!eth_getenv_enetaddr("ethaddr", v_mac)) {
708 /* get ROM mac value if any */
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500709 if (!get_rom_mac(dev, v_mac)) {
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500710 printf("\n*** ERROR: ethaddr is NOT set !!\n");
711 return -1;
wdenk5ca26792004-06-06 22:11:41 +0000712 }
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500713 eth_setenv_enetaddr("ethaddr", v_mac);
wdenk5ca26792004-06-06 22:11:41 +0000714 }
715
Mike Frysinger03f3d8d2009-02-11 19:09:54 -0500716 smc_set_mac_addr(v_mac); /* use old function to update smc default */
717 PRINTK("Using MAC Address %pM\n", v_mac);
718 return 0;
wdenk5ca26792004-06-06 22:11:41 +0000719}
720
wdenka56bd922004-06-06 23:13:55 +0000721/*
wdenk5ca26792004-06-06 22:11:41 +0000722 * get_rom_mac()
723 * Note, this has omly been tested for the OMAP730 P2.
724 */
725
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500726static int get_rom_mac(struct eth_device *dev, unsigned char *v_rom_mac)
wdenk5ca26792004-06-06 22:11:41 +0000727{
wdenk5ca26792004-06-06 22:11:41 +0000728 int i;
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500729 SMC_SELECT_BANK(dev, 1);
wdenk5ca26792004-06-06 22:11:41 +0000730 for (i=0; i<6; i++)
731 {
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500732 v_rom_mac[i] = SMC_inb(dev, LAN91C96_IA0 + i);
wdenk5ca26792004-06-06 22:11:41 +0000733 }
734 return (1);
wdenk5ca26792004-06-06 22:11:41 +0000735}
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500736
737/* Structure to detect the device IDs */
738struct id_type {
739 u8 id;
740 char *name;
741};
742static struct id_type supported_chips[] = {
743 {0, ""}, /* Dummy entry to prevent id check failure */
744 {9, "LAN91C110"},
745 {8, "LAN91C100FD"},
746 {7, "LAN91C100"},
747 {5, "LAN91C95"},
Yanjun Yang0e7790d2010-12-26 10:40:54 +0800748 {4, "LAN91C94/96"},
749 {3, "LAN91C90/92"},
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500750};
751/* lan91c96_detect_chip
752 * See:
753 * http://www.embeddedsys.com/subpages/resources/images/documents/LAN91C96_datasheet.pdf
754 * page 71 - that is the closest we get to detect this device
755 */
756static int lan91c96_detect_chip(struct eth_device *dev)
757{
758 u8 chip_id;
759 int r;
760 SMC_SELECT_BANK(dev, 3);
Yanjun Yang16721712010-12-28 16:08:25 +0800761 chip_id = (SMC_inw(dev, 0xA) & LAN91C96_REV_CHIPID) >> 4;
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500762 SMC_SELECT_BANK(dev, 0);
Axel Lina62cd292013-07-03 11:24:18 +0800763 for (r = 0; r < ARRAY_SIZE(supported_chips); r++)
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500764 if (chip_id == supported_chips[r].id)
765 return r;
766 return 0;
767}
768
769int lan91c96_initialize(u8 dev_num, int base_addr)
770{
771 struct eth_device *dev;
772 int r = 0;
773
774 dev = malloc(sizeof(*dev));
775 if (!dev) {
Nishanth Menonb7ad4102009-10-16 00:06:35 -0500776 return 0;
777 }
778 memset(dev, 0, sizeof(*dev));
779
780 dev->iobase = base_addr;
781
782 /* Try to detect chip. Will fail if not present. */
783 r = lan91c96_detect_chip(dev);
784 if (!r) {
785 free(dev);
786 return 0;
787 }
788 get_rom_mac(dev, dev->enetaddr);
789
790 dev->init = lan91c96_init;
791 dev->halt = lan91c96_halt;
792 dev->send = lan91c96_send;
793 dev->recv = lan91c96_recv;
794 sprintf(dev->name, "%s-%hu", supported_chips[r].name, dev_num);
795
796 eth_register(dev);
797 return 0;
798}