1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2004
4 * Robin Getz rgetz@blacfin.uclinux.org
5 *
6 * Heavily borrowed from the following peoples GPL'ed software:
7 * - Wolfgang Denk, DENX Software Engineering, wd@denx.de
8 * Das U-Boot
9 * - 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>
15 #include <linux/delay.h>
16 #include "../drivers/net/smc91111.h"
17
18 #ifndef SMC91111_EEPROM_INIT
19 # define SMC91111_EEPROM_INIT()
20 #endif
21
22 #define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE
23 #define EEPROM 0x1
24 #define MAC 0x2
25 #define UNKNOWN 0x4
26
27 void dump_reg (struct eth_device *dev);
28 void dump_eeprom (struct eth_device *dev);
29 int write_eeprom_reg (struct eth_device *dev, int value, int reg);
30 void copy_from_eeprom (struct eth_device *dev);
31 void print_MAC (struct eth_device *dev);
32 int read_eeprom_reg (struct eth_device *dev, int reg);
33 void print_macaddr (struct eth_device *dev);
34
smc91111_eeprom(int argc,char * const argv[])35 int smc91111_eeprom(int argc, char *const argv[])
36 {
37 int c, i, j, done, line, reg, value, start, what;
38 char input[50];
39
40 struct eth_device dev;
41 dev.iobase = CONFIG_SMC91111_BASE;
42
43 /* 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
53 SMC91111_EEPROM_INIT();
54
55 if ((SMC_inw (&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
56 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:
198 printf ("Writing EEPROM register %02x with %04x\n", reg, value);
199 write_eeprom_reg (&dev, value, reg);
200 break;
201 case 2:
202 printf ("Writing MAC register bank %i, reg %02x with %04x\n", reg >> 4, reg & 0xE, value);
203 SMC_SELECT_BANK (&dev, reg >> 4);
204 SMC_outw (&dev, value, reg & 0xE);
205 break;
206 default:
207 printf ("Wrong\n");
208 break;
209 }
210 break;
211 case ('D'):
212 dump_eeprom (&dev);
213 break;
214 case ('M'):
215 dump_reg (&dev);
216 break;
217 case ('C'):
218 copy_from_eeprom (&dev);
219 break;
220 case ('P'):
221 print_macaddr (&dev);
222 break;
223 default:
224 break;
225 }
226
227 }
228
229 return (0);
230 }
231
copy_from_eeprom(struct eth_device * dev)232 void copy_from_eeprom (struct eth_device *dev)
233 {
234 int i;
235
236 SMC_SELECT_BANK (dev, 1);
237 SMC_outw (dev, (SMC_inw (dev, CTL_REG) & !CTL_EEPROM_SELECT) |
238 CTL_RELOAD, CTL_REG);
239 i = 100;
240 while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --i)
241 udelay(100);
242 if (i == 0) {
243 printf ("Timeout Refreshing EEPROM registers\n");
244 } else {
245 printf ("EEPROM contents copied to MAC\n");
246 }
247
248 }
249
print_macaddr(struct eth_device * dev)250 void print_macaddr (struct eth_device *dev)
251 {
252 int i, j, k, mac[6];
253
254 printf ("Current MAC Address in SMSC91111 ");
255 SMC_SELECT_BANK (dev, 1);
256 for (i = 0; i < 5; i++) {
257 printf ("%02x:", SMC_inb (dev, ADDR0_REG + i));
258 }
259
260 printf ("%02x\n", SMC_inb (dev, ADDR0_REG + 5));
261
262 i = 0;
263 for (j = 0x20; j < 0x23; j++) {
264 k = read_eeprom_reg (dev, j);
265 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 }
dump_eeprom(struct eth_device * dev)277 void dump_eeprom (struct eth_device *dev)
278 {
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) {
295 printf ("%02x:%04x ", j + k,
296 read_eeprom_reg (dev, j + k));
297 }
298 printf ("\n");
299 }
300
301 for (j = 0x20; j < 0x40; j++) {
302 if ((j & 0x07) == 0)
303 printf ("\n");
304 printf ("%02x:%04x ", j, read_eeprom_reg (dev, j));
305 }
306 printf ("\n");
307
308 }
309
read_eeprom_reg(struct eth_device * dev,int reg)310 int read_eeprom_reg (struct eth_device *dev, int reg)
311 {
312 int timeout;
313
314 SMC_SELECT_BANK (dev, 2);
315 SMC_outw (dev, reg, PTR_REG);
316
317 SMC_SELECT_BANK (dev, 1);
318 SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
319 CTL_RELOAD, CTL_REG);
320 timeout = 100;
321 while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
322 udelay(100);
323 if (timeout == 0) {
324 printf ("Timeout Reading EEPROM register %02x\n", reg);
325 return 0;
326 }
327
328 return SMC_inw (dev, GP_REG);
329
330 }
331
write_eeprom_reg(struct eth_device * dev,int value,int reg)332 int write_eeprom_reg (struct eth_device *dev, int value, int reg)
333 {
334 int timeout;
335
336 SMC_SELECT_BANK (dev, 2);
337 SMC_outw (dev, reg, PTR_REG);
338
339 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);
343 timeout = 100;
344 while ((SMC_inw (dev, CTL_REG) & CTL_STORE) && --timeout)
345 udelay(100);
346 if (timeout == 0) {
347 printf ("Timeout Writing EEPROM register %02x\n", reg);
348 return 0;
349 }
350
351 return 1;
352
353 }
354
dump_reg(struct eth_device * dev)355 void dump_reg (struct eth_device *dev)
356 {
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++) {
367 SMC_SELECT_BANK (dev, j);
368 printf ("%04x ", SMC_inw (dev, i));
369 }
370 printf ("\n");
371 }
372 }
373