blob: bf7e93064309f2ef6b8fbf8bedc133da0a9b01b1 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk5a95f6f2005-01-12 00:38:03 +00002/*
3 * (C) Copyright 2004
4 * Robin Getz rgetz@blacfin.uclinux.org
5 *
wdenk5a95f6f2005-01-12 00:38:03 +00006 * Heavily borrowed from the following peoples GPL'ed software:
7 * - Wolfgang Denk, DENX Software Engineering, wd@denx.de
Bin Menga1875592016-02-05 19:30:11 -08008 * Das U-Boot
wdenk5a95f6f2005-01-12 00:38:03 +00009 * - Ladislav Michl ladis@linux-mips.org
10 * A rejected patch on the U-Boot mailing list
11 */
12
13#include <common.h>
14#include <exports.h>
Simon Glassc05ed002020-05-10 11:40:11 -060015#include <linux/delay.h>
Jean-Christophe PLAGNIOL-VILLARD2439e4b2007-11-21 21:19:24 +010016#include "../drivers/net/smc91111.h"
wdenk5a95f6f2005-01-12 00:38:03 +000017
Mike Frysingerb196ca72009-03-22 22:18:01 -040018#ifndef SMC91111_EEPROM_INIT
19# define SMC91111_EEPROM_INIT()
Mike Frysinger6b9097e2008-02-04 19:26:56 -050020#endif
21
wdenk5a95f6f2005-01-12 00:38:03 +000022#define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE
Mike Frysingerb196ca72009-03-22 22:18:01 -040023#define EEPROM 0x1
24#define MAC 0x2
25#define UNKNOWN 0x4
wdenk5a95f6f2005-01-12 00:38:03 +000026
Ben Warren7194ab82009-10-04 22:37:03 -070027void dump_reg (struct eth_device *dev);
28void dump_eeprom (struct eth_device *dev);
29int write_eeprom_reg (struct eth_device *dev, int value, int reg);
30void copy_from_eeprom (struct eth_device *dev);
31void print_MAC (struct eth_device *dev);
32int read_eeprom_reg (struct eth_device *dev, int reg);
33void print_macaddr (struct eth_device *dev);
wdenk5a95f6f2005-01-12 00:38:03 +000034
Simon Glass09140112020-05-10 11:40:03 -060035int smc91111_eeprom(int argc, char *const argv[])
wdenk5a95f6f2005-01-12 00:38:03 +000036{
37 int c, i, j, done, line, reg, value, start, what;
38 char input[50];
39
Mike Frysingerc4168af2010-01-21 05:04:59 -050040 struct eth_device dev;
41 dev.iobase = CONFIG_SMC91111_BASE;
Ben Warren7194ab82009-10-04 22:37:03 -070042
wdenk5a95f6f2005-01-12 00:38:03 +000043 /* Print the ABI version */
44 app_startup (argv);
45 if (XF_VERSION != (int) get_version ()) {
46 printf ("Expects ABI version %d\n", XF_VERSION);
47 printf ("Actual U-Boot ABI version %d\n",
48 (int) get_version ());
49 printf ("Can't run\n\n");
50 return (0);
51 }
52
Mike Frysingerb196ca72009-03-22 22:18:01 -040053 SMC91111_EEPROM_INIT();
wdenk5a95f6f2005-01-12 00:38:03 +000054
Ben Warren7194ab82009-10-04 22:37:03 -070055 if ((SMC_inw (&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
wdenk5a95f6f2005-01-12 00:38:03 +000056 printf ("Can't find SMSC91111\n");
57 return (0);
58 }
59
60 done = 0;
61 what = UNKNOWN;
62 printf ("\n");
63 while (!done) {
64 /* print the prompt */
65 printf ("SMC91111> ");
66 line = 0;
67 i = 0;
68 start = 1;
69 while (!line) {
70 /* Wait for a keystroke */
71 while (!tstc ());
72
73 c = getc ();
74 /* Make Uppercase */
75 if (c >= 'Z')
76 c -= ('a' - 'A');
77 /* printf(" |%02x| ",c); */
78
79 switch (c) {
80 case '\r': /* Enter */
81 case '\n':
82 input[i] = 0;
83 puts ("\r\n");
84 line = 1;
85 break;
86 case '\0': /* nul */
87 continue;
88
89 case 0x03: /* ^C - break */
90 input[0] = 0;
91 i = 0;
92 line = 1;
93 done = 1;
94 break;
95
96 case 0x5F:
97 case 0x08: /* ^H - backspace */
98 case 0x7F: /* DEL - backspace */
99 if (i > 0) {
100 puts ("\b \b");
101 i--;
102 }
103 break;
104 default:
105 if (start) {
106 if ((c == 'W') || (c == 'D')
107 || (c == 'M') || (c == 'C')
108 || (c == 'P')) {
109 putc (c);
110 input[i] = c;
111 if (i <= 45)
112 i++;
113 start = 0;
114 }
115 } else {
116 if ((c >= '0' && c <= '9')
117 || (c >= 'A' && c <= 'F')
118 || (c == 'E') || (c == 'M')
119 || (c == ' ')) {
120 putc (c);
121 input[i] = c;
122 if (i <= 45)
123 i++;
124 break;
125 }
126 }
127 break;
128 }
129 }
130
131 for (; i < 49; i++)
132 input[i] = 0;
133
134 switch (input[0]) {
135 case ('W'):
136 /* Line should be w reg value */
137 i = 0;
138 reg = 0;
139 value = 0;
140 /* Skip to the next space or end) */
141 while ((input[i] != ' ') && (input[i] != 0))
142 i++;
143
144 if (input[i] != 0)
145 i++;
146
147 /* Are we writing to EEPROM or MAC */
148 switch (input[i]) {
149 case ('E'):
150 what = EEPROM;
151 break;
152 case ('M'):
153 what = MAC;
154 break;
155 default:
156 what = UNKNOWN;
157 break;
158 }
159
160 /* skip to the next space or end */
161 while ((input[i] != ' ') && (input[i] != 0))
162 i++;
163 if (input[i] != 0)
164 i++;
165
166 /* Find register to write into */
167 j = 0;
168 while ((input[i] != ' ') && (input[i] != 0)) {
169 j = input[i] - 0x30;
170 if (j >= 0xA) {
171 j -= 0x07;
172 }
173 reg = (reg * 0x10) + j;
174 i++;
175 }
176
177 while ((input[i] != ' ') && (input[i] != 0))
178 i++;
179
180 if (input[i] != 0)
181 i++;
182 else
183 what = UNKNOWN;
184
185 /* Get the value to write */
186 j = 0;
187 while ((input[i] != ' ') && (input[i] != 0)) {
188 j = input[i] - 0x30;
189 if (j >= 0xA) {
190 j -= 0x07;
191 }
192 value = (value * 0x10) + j;
193 i++;
194 }
195
196 switch (what) {
197 case 1:
Wolfgang Denk0afe5192006-03-12 02:10:00 +0100198 printf ("Writing EEPROM register %02x with %04x\n", reg, value);
Ben Warren7194ab82009-10-04 22:37:03 -0700199 write_eeprom_reg (&dev, value, reg);
wdenk5a95f6f2005-01-12 00:38:03 +0000200 break;
201 case 2:
Wolfgang Denk0afe5192006-03-12 02:10:00 +0100202 printf ("Writing MAC register bank %i, reg %02x with %04x\n", reg >> 4, reg & 0xE, value);
Ben Warren7194ab82009-10-04 22:37:03 -0700203 SMC_SELECT_BANK (&dev, reg >> 4);
204 SMC_outw (&dev, value, reg & 0xE);
wdenk5a95f6f2005-01-12 00:38:03 +0000205 break;
206 default:
207 printf ("Wrong\n");
208 break;
209 }
210 break;
211 case ('D'):
Ben Warren7194ab82009-10-04 22:37:03 -0700212 dump_eeprom (&dev);
wdenk5a95f6f2005-01-12 00:38:03 +0000213 break;
214 case ('M'):
Ben Warren7194ab82009-10-04 22:37:03 -0700215 dump_reg (&dev);
wdenk5a95f6f2005-01-12 00:38:03 +0000216 break;
217 case ('C'):
Ben Warren7194ab82009-10-04 22:37:03 -0700218 copy_from_eeprom (&dev);
wdenk5a95f6f2005-01-12 00:38:03 +0000219 break;
220 case ('P'):
Ben Warren7194ab82009-10-04 22:37:03 -0700221 print_macaddr (&dev);
wdenk5a95f6f2005-01-12 00:38:03 +0000222 break;
223 default:
224 break;
225 }
226
227 }
228
229 return (0);
230}
231
Ben Warren7194ab82009-10-04 22:37:03 -0700232void copy_from_eeprom (struct eth_device *dev)
wdenk5a95f6f2005-01-12 00:38:03 +0000233{
234 int i;
235
Ben Warren7194ab82009-10-04 22:37:03 -0700236 SMC_SELECT_BANK (dev, 1);
237 SMC_outw (dev, (SMC_inw (dev, CTL_REG) & !CTL_EEPROM_SELECT) |
238 CTL_RELOAD, CTL_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000239 i = 100;
Ben Warren7194ab82009-10-04 22:37:03 -0700240 while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --i)
Simon Glass07e11142020-05-10 11:40:10 -0600241 udelay(100);
wdenk5a95f6f2005-01-12 00:38:03 +0000242 if (i == 0) {
243 printf ("Timeout Refreshing EEPROM registers\n");
244 } else {
245 printf ("EEPROM contents copied to MAC\n");
246 }
247
248}
249
Ben Warren7194ab82009-10-04 22:37:03 -0700250void print_macaddr (struct eth_device *dev)
wdenk5a95f6f2005-01-12 00:38:03 +0000251{
252 int i, j, k, mac[6];
253
254 printf ("Current MAC Address in SMSC91111 ");
Ben Warren7194ab82009-10-04 22:37:03 -0700255 SMC_SELECT_BANK (dev, 1);
wdenk5a95f6f2005-01-12 00:38:03 +0000256 for (i = 0; i < 5; i++) {
Ben Warren7194ab82009-10-04 22:37:03 -0700257 printf ("%02x:", SMC_inb (dev, ADDR0_REG + i));
wdenk5a95f6f2005-01-12 00:38:03 +0000258 }
259
Ben Warren7194ab82009-10-04 22:37:03 -0700260 printf ("%02x\n", SMC_inb (dev, ADDR0_REG + 5));
wdenk5a95f6f2005-01-12 00:38:03 +0000261
262 i = 0;
263 for (j = 0x20; j < 0x23; j++) {
Ben Warren7194ab82009-10-04 22:37:03 -0700264 k = read_eeprom_reg (dev, j);
wdenk5a95f6f2005-01-12 00:38:03 +0000265 mac[i] = k & 0xFF;
266 i++;
267 mac[i] = k >> 8;
268 i++;
269 }
270
271 printf ("Current MAC Address in EEPROM ");
272 for (i = 0; i < 5; i++)
273 printf ("%02x:", mac[i]);
274 printf ("%02x\n", mac[5]);
275
276}
Ben Warren7194ab82009-10-04 22:37:03 -0700277void dump_eeprom (struct eth_device *dev)
wdenk5a95f6f2005-01-12 00:38:03 +0000278{
279 int j, k;
280
281 printf ("IOS2-0 ");
282 for (j = 0; j < 8; j++) {
283 printf ("%03x ", j);
284 }
285 printf ("\n");
286
287 for (k = 0; k < 4; k++) {
288 if (k == 0)
289 printf ("CONFIG ");
290 if (k == 1)
291 printf ("BASE ");
292 if ((k == 2) || (k == 3))
293 printf (" ");
294 for (j = 0; j < 0x20; j += 4) {
Ben Warren7194ab82009-10-04 22:37:03 -0700295 printf ("%02x:%04x ", j + k,
296 read_eeprom_reg (dev, j + k));
wdenk5a95f6f2005-01-12 00:38:03 +0000297 }
298 printf ("\n");
299 }
300
301 for (j = 0x20; j < 0x40; j++) {
302 if ((j & 0x07) == 0)
303 printf ("\n");
Ben Warren7194ab82009-10-04 22:37:03 -0700304 printf ("%02x:%04x ", j, read_eeprom_reg (dev, j));
wdenk5a95f6f2005-01-12 00:38:03 +0000305 }
306 printf ("\n");
307
308}
309
Ben Warren7194ab82009-10-04 22:37:03 -0700310int read_eeprom_reg (struct eth_device *dev, int reg)
wdenk5a95f6f2005-01-12 00:38:03 +0000311{
312 int timeout;
313
Ben Warren7194ab82009-10-04 22:37:03 -0700314 SMC_SELECT_BANK (dev, 2);
315 SMC_outw (dev, reg, PTR_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000316
Ben Warren7194ab82009-10-04 22:37:03 -0700317 SMC_SELECT_BANK (dev, 1);
318 SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
319 CTL_RELOAD, CTL_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000320 timeout = 100;
Ben Warren7194ab82009-10-04 22:37:03 -0700321 while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
Simon Glass07e11142020-05-10 11:40:10 -0600322 udelay(100);
wdenk5a95f6f2005-01-12 00:38:03 +0000323 if (timeout == 0) {
324 printf ("Timeout Reading EEPROM register %02x\n", reg);
325 return 0;
326 }
327
Ben Warren7194ab82009-10-04 22:37:03 -0700328 return SMC_inw (dev, GP_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000329
330}
331
Ben Warren7194ab82009-10-04 22:37:03 -0700332int write_eeprom_reg (struct eth_device *dev, int value, int reg)
wdenk5a95f6f2005-01-12 00:38:03 +0000333{
334 int timeout;
335
Ben Warren7194ab82009-10-04 22:37:03 -0700336 SMC_SELECT_BANK (dev, 2);
337 SMC_outw (dev, reg, PTR_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000338
Ben Warren7194ab82009-10-04 22:37:03 -0700339 SMC_SELECT_BANK (dev, 1);
340 SMC_outw (dev, value, GP_REG);
341 SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
342 CTL_STORE, CTL_REG);
wdenk5a95f6f2005-01-12 00:38:03 +0000343 timeout = 100;
Ben Warren7194ab82009-10-04 22:37:03 -0700344 while ((SMC_inw (dev, CTL_REG) & CTL_STORE) && --timeout)
Simon Glass07e11142020-05-10 11:40:10 -0600345 udelay(100);
wdenk5a95f6f2005-01-12 00:38:03 +0000346 if (timeout == 0) {
347 printf ("Timeout Writing EEPROM register %02x\n", reg);
348 return 0;
349 }
350
351 return 1;
352
353}
354
Ben Warren7194ab82009-10-04 22:37:03 -0700355void dump_reg (struct eth_device *dev)
wdenk5a95f6f2005-01-12 00:38:03 +0000356{
357 int i, j;
358
359 printf (" ");
360 for (j = 0; j < 4; j++) {
361 printf ("Bank%i ", j);
362 }
363 printf ("\n");
364 for (i = 0; i < 0xF; i += 2) {
365 printf ("%02x ", i);
366 for (j = 0; j < 4; j++) {
Ben Warren7194ab82009-10-04 22:37:03 -0700367 SMC_SELECT_BANK (dev, j);
368 printf ("%04x ", SMC_inw (dev, i));
wdenk5a95f6f2005-01-12 00:38:03 +0000369 }
370 printf ("\n");
371 }
372}