blob: b91f34c3af0593095d262c84e8345ca9af6e925a [file] [log] [blame]
wdenk5a95f6f2005-01-12 00:38:03 +00001/*
2 * (C) Copyright 2004
3 * Robin Getz rgetz@blacfin.uclinux.org
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 *
23 * Heavily borrowed from the following peoples GPL'ed software:
24 * - Wolfgang Denk, DENX Software Engineering, wd@denx.de
25 * Das U-boot
26 * - Ladislav Michl ladis@linux-mips.org
27 * A rejected patch on the U-Boot mailing list
28 */
29
30#include <common.h>
31#include <exports.h>
Jean-Christophe PLAGNIOL-VILLARD2439e4b2007-11-21 21:19:24 +010032#include "../drivers/net/smc91111.h"
wdenk5a95f6f2005-01-12 00:38:03 +000033
Mike Frysingerb196ca72009-03-22 22:18:01 -040034#ifndef SMC91111_EEPROM_INIT
35# define SMC91111_EEPROM_INIT()
Mike Frysinger6b9097e2008-02-04 19:26:56 -050036#endif
37
wdenk5a95f6f2005-01-12 00:38:03 +000038#define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE
Mike Frysingerb196ca72009-03-22 22:18:01 -040039#define EEPROM 0x1
40#define MAC 0x2
41#define UNKNOWN 0x4
wdenk5a95f6f2005-01-12 00:38:03 +000042
Ben Warren7194ab82009-10-04 22:37:03 -070043void dump_reg (struct eth_device *dev);
44void dump_eeprom (struct eth_device *dev);
45int write_eeprom_reg (struct eth_device *dev, int value, int reg);
46void copy_from_eeprom (struct eth_device *dev);
47void print_MAC (struct eth_device *dev);
48int read_eeprom_reg (struct eth_device *dev, int reg);
49void print_macaddr (struct eth_device *dev);
wdenk5a95f6f2005-01-12 00:38:03 +000050
51int smc91111_eeprom (int argc, char *argv[])
52{
53 int c, i, j, done, line, reg, value, start, what;
54 char input[50];
55
Mike Frysingerc4168af2010-01-21 05:04:59 -050056 struct eth_device dev;
57 dev.iobase = CONFIG_SMC91111_BASE;
Ben Warren7194ab82009-10-04 22:37:03 -070058
wdenk5a95f6f2005-01-12 00:38:03 +000059 /* Print the ABI version */
60 app_startup (argv);
61 if (XF_VERSION != (int) get_version ()) {
62 printf ("Expects ABI version %d\n", XF_VERSION);
63 printf ("Actual U-Boot ABI version %d\n",
64 (int) get_version ());
65 printf ("Can't run\n\n");
66 return (0);
67 }
68
Mike Frysingerb196ca72009-03-22 22:18:01 -040069 SMC91111_EEPROM_INIT();
wdenk5a95f6f2005-01-12 00:38:03 +000070
Ben Warren7194ab82009-10-04 22:37:03 -070071 if ((SMC_inw (&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
wdenk5a95f6f2005-01-12 00:38:03 +000072 printf ("Can't find SMSC91111\n");
73 return (0);
74 }
75
76 done = 0;
77 what = UNKNOWN;
78 printf ("\n");
79 while (!done) {
80 /* print the prompt */
81 printf ("SMC91111> ");
82 line = 0;
83 i = 0;
84 start = 1;
85 while (!line) {
86 /* Wait for a keystroke */
87 while (!tstc ());
88
89 c = getc ();
90 /* Make Uppercase */
91 if (c >= 'Z')
92 c -= ('a' - 'A');
93 /* printf(" |%02x| ",c); */
94
95 switch (c) {
96 case '\r': /* Enter */
97 case '\n':
98 input[i] = 0;
99 puts ("\r\n");
100 line = 1;
101 break;
102 case '\0': /* nul */
103 continue;
104
105 case 0x03: /* ^C - break */
106 input[0] = 0;
107 i = 0;
108 line = 1;
109 done = 1;
110 break;
111
112 case 0x5F:
113 case 0x08: /* ^H - backspace */
114 case 0x7F: /* DEL - backspace */
115 if (i > 0) {
116 puts ("\b \b");
117 i--;
118 }
119 break;
120 default:
121 if (start) {
122 if ((c == 'W') || (c == 'D')
123 || (c == 'M') || (c == 'C')
124 || (c == 'P')) {
125 putc (c);
126 input[i] = c;
127 if (i <= 45)
128 i++;
129 start = 0;
130 }
131 } else {
132 if ((c >= '0' && c <= '9')
133 || (c >= 'A' && c <= 'F')
134 || (c == 'E') || (c == 'M')
135 || (c == ' ')) {
136 putc (c);
137 input[i] = c;
138 if (i <= 45)
139 i++;
140 break;
141 }
142 }
143 break;
144 }
145 }
146
147 for (; i < 49; i++)
148 input[i] = 0;
149
150 switch (input[0]) {
151 case ('W'):
152 /* Line should be w reg value */
153 i = 0;
154 reg = 0;
155 value = 0;
156 /* Skip to the next space or end) */
157 while ((input[i] != ' ') && (input[i] != 0))
158 i++;
159
160 if (input[i] != 0)
161 i++;
162
163 /* Are we writing to EEPROM or MAC */
164 switch (input[i]) {
165 case ('E'):
166 what = EEPROM;
167 break;
168 case ('M'):
169 what = MAC;
170 break;
171 default:
172 what = UNKNOWN;
173 break;
174 }
175
176 /* skip to the next space or end */
177 while ((input[i] != ' ') && (input[i] != 0))
178 i++;
179 if (input[i] != 0)
180 i++;
181
182 /* Find register to write into */
183 j = 0;
184 while ((input[i] != ' ') && (input[i] != 0)) {
185 j = input[i] - 0x30;
186 if (j >= 0xA) {
187 j -= 0x07;
188 }
189 reg = (reg * 0x10) + j;
190 i++;
191 }
192
193 while ((input[i] != ' ') && (input[i] != 0))
194 i++;
195
196 if (input[i] != 0)
197 i++;
198 else
199 what = UNKNOWN;
200
201 /* Get the value to write */
202 j = 0;
203 while ((input[i] != ' ') && (input[i] != 0)) {
204 j = input[i] - 0x30;
205 if (j >= 0xA) {
206 j -= 0x07;
207 }
208 value = (value * 0x10) + j;
209 i++;
210 }
211
212 switch (what) {
213 case 1:
Wolfgang Denk0afe5192006-03-12 02:10:00 +0100214 printf ("Writing EEPROM register %02x with %04x\n", reg, value);
Ben Warren7194ab82009-10-04 22:37:03 -0700215 write_eeprom_reg (&dev, value, reg);
wdenk5a95f6f2005-01-12 00:38:03 +0000216 break;
217 case 2:
Wolfgang Denk0afe5192006-03-12 02:10:00 +0100218 printf ("Writing MAC register bank %i, reg %02x with %04x\n", reg >> 4, reg & 0xE, value);
Ben Warren7194ab82009-10-04 22:37:03 -0700219 SMC_SELECT_BANK (&dev, reg >> 4);
220 SMC_outw (&dev, value, reg & 0xE);
wdenk5a95f6f2005-01-12 00:38:03 +0000221 break;
222 default:
223 printf ("Wrong\n");
224 break;
225 }
226 break;
227 case ('D'):
Ben Warren7194ab82009-10-04 22:37:03 -0700228 dump_eeprom (&dev);
wdenk5a95f6f2005-01-12 00:38:03 +0000229 break;
230 case ('M'):
Ben Warren7194ab82009-10-04 22:37:03 -0700231 dump_reg (&dev);
wdenk5a95f6f2005-01-12 00:38:03 +0000232 break;
233 case ('C'):
Ben Warren7194ab82009-10-04 22:37:03 -0700234 copy_from_eeprom (&dev);
wdenk5a95f6f2005-01-12 00:38:03 +0000235 break;
236 case ('P'):
Ben Warren7194ab82009-10-04 22:37:03 -0700237 print_macaddr (&dev);
wdenk5a95f6f2005-01-12 00:38:03 +0000238 break;
239 default:
240 break;
241 }
242
243 }
244
245 return (0);
246}
247
Ben Warren7194ab82009-10-04 22:37:03 -0700248void copy_from_eeprom (struct eth_device *dev)
wdenk5a95f6f2005-01-12 00:38:03 +0000249{
250 int i;
251
Ben Warren7194ab82009-10-04 22:37:03 -0700252 SMC_SELECT_BANK (dev, 1);
253 SMC_outw (dev, (SMC_inw (dev, CTL_REG) & !CTL_EEPROM_SELECT) |
254 CTL_RELOAD, CTL_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000255 i = 100;
Ben Warren7194ab82009-10-04 22:37:03 -0700256 while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --i)
wdenk5a95f6f2005-01-12 00:38:03 +0000257 udelay (100);
258 if (i == 0) {
259 printf ("Timeout Refreshing EEPROM registers\n");
260 } else {
261 printf ("EEPROM contents copied to MAC\n");
262 }
263
264}
265
Ben Warren7194ab82009-10-04 22:37:03 -0700266void print_macaddr (struct eth_device *dev)
wdenk5a95f6f2005-01-12 00:38:03 +0000267{
268 int i, j, k, mac[6];
269
270 printf ("Current MAC Address in SMSC91111 ");
Ben Warren7194ab82009-10-04 22:37:03 -0700271 SMC_SELECT_BANK (dev, 1);
wdenk5a95f6f2005-01-12 00:38:03 +0000272 for (i = 0; i < 5; i++) {
Ben Warren7194ab82009-10-04 22:37:03 -0700273 printf ("%02x:", SMC_inb (dev, ADDR0_REG + i));
wdenk5a95f6f2005-01-12 00:38:03 +0000274 }
275
Ben Warren7194ab82009-10-04 22:37:03 -0700276 printf ("%02x\n", SMC_inb (dev, ADDR0_REG + 5));
wdenk5a95f6f2005-01-12 00:38:03 +0000277
278 i = 0;
279 for (j = 0x20; j < 0x23; j++) {
Ben Warren7194ab82009-10-04 22:37:03 -0700280 k = read_eeprom_reg (dev, j);
wdenk5a95f6f2005-01-12 00:38:03 +0000281 mac[i] = k & 0xFF;
282 i++;
283 mac[i] = k >> 8;
284 i++;
285 }
286
287 printf ("Current MAC Address in EEPROM ");
288 for (i = 0; i < 5; i++)
289 printf ("%02x:", mac[i]);
290 printf ("%02x\n", mac[5]);
291
292}
Ben Warren7194ab82009-10-04 22:37:03 -0700293void dump_eeprom (struct eth_device *dev)
wdenk5a95f6f2005-01-12 00:38:03 +0000294{
295 int j, k;
296
297 printf ("IOS2-0 ");
298 for (j = 0; j < 8; j++) {
299 printf ("%03x ", j);
300 }
301 printf ("\n");
302
303 for (k = 0; k < 4; k++) {
304 if (k == 0)
305 printf ("CONFIG ");
306 if (k == 1)
307 printf ("BASE ");
308 if ((k == 2) || (k == 3))
309 printf (" ");
310 for (j = 0; j < 0x20; j += 4) {
Ben Warren7194ab82009-10-04 22:37:03 -0700311 printf ("%02x:%04x ", j + k,
312 read_eeprom_reg (dev, j + k));
wdenk5a95f6f2005-01-12 00:38:03 +0000313 }
314 printf ("\n");
315 }
316
317 for (j = 0x20; j < 0x40; j++) {
318 if ((j & 0x07) == 0)
319 printf ("\n");
Ben Warren7194ab82009-10-04 22:37:03 -0700320 printf ("%02x:%04x ", j, read_eeprom_reg (dev, j));
wdenk5a95f6f2005-01-12 00:38:03 +0000321 }
322 printf ("\n");
323
324}
325
Ben Warren7194ab82009-10-04 22:37:03 -0700326int read_eeprom_reg (struct eth_device *dev, int reg)
wdenk5a95f6f2005-01-12 00:38:03 +0000327{
328 int timeout;
329
Ben Warren7194ab82009-10-04 22:37:03 -0700330 SMC_SELECT_BANK (dev, 2);
331 SMC_outw (dev, reg, PTR_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000332
Ben Warren7194ab82009-10-04 22:37:03 -0700333 SMC_SELECT_BANK (dev, 1);
334 SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
335 CTL_RELOAD, CTL_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000336 timeout = 100;
Ben Warren7194ab82009-10-04 22:37:03 -0700337 while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
wdenk5a95f6f2005-01-12 00:38:03 +0000338 udelay (100);
339 if (timeout == 0) {
340 printf ("Timeout Reading EEPROM register %02x\n", reg);
341 return 0;
342 }
343
Ben Warren7194ab82009-10-04 22:37:03 -0700344 return SMC_inw (dev, GP_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000345
346}
347
Ben Warren7194ab82009-10-04 22:37:03 -0700348int write_eeprom_reg (struct eth_device *dev, int value, int reg)
wdenk5a95f6f2005-01-12 00:38:03 +0000349{
350 int timeout;
351
Ben Warren7194ab82009-10-04 22:37:03 -0700352 SMC_SELECT_BANK (dev, 2);
353 SMC_outw (dev, reg, PTR_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000354
Ben Warren7194ab82009-10-04 22:37:03 -0700355 SMC_SELECT_BANK (dev, 1);
356 SMC_outw (dev, value, GP_REG);
357 SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
358 CTL_STORE, CTL_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000359 timeout = 100;
Ben Warren7194ab82009-10-04 22:37:03 -0700360 while ((SMC_inw (dev, CTL_REG) & CTL_STORE) && --timeout)
wdenk5a95f6f2005-01-12 00:38:03 +0000361 udelay (100);
362 if (timeout == 0) {
363 printf ("Timeout Writing EEPROM register %02x\n", reg);
364 return 0;
365 }
366
367 return 1;
368
369}
370
Ben Warren7194ab82009-10-04 22:37:03 -0700371void dump_reg (struct eth_device *dev)
wdenk5a95f6f2005-01-12 00:38:03 +0000372{
373 int i, j;
374
375 printf (" ");
376 for (j = 0; j < 4; j++) {
377 printf ("Bank%i ", j);
378 }
379 printf ("\n");
380 for (i = 0; i < 0xF; i += 2) {
381 printf ("%02x ", i);
382 for (j = 0; j < 4; j++) {
Ben Warren7194ab82009-10-04 22:37:03 -0700383 SMC_SELECT_BANK (dev, j);
384 printf ("%04x ", SMC_inw (dev, i));
wdenk5a95f6f2005-01-12 00:38:03 +0000385 }
386 printf ("\n");
387 }
388}