1 /*
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>
32 #include "../drivers/net/smc91111.h"
33 
34 #ifndef SMC91111_EEPROM_INIT
35 # define SMC91111_EEPROM_INIT()
36 #endif
37 
38 #define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE
39 #define EEPROM		0x1
40 #define MAC		0x2
41 #define UNKNOWN		0x4
42 
43 void dump_reg (struct eth_device *dev);
44 void dump_eeprom (struct eth_device *dev);
45 int write_eeprom_reg (struct eth_device *dev, int value, int reg);
46 void copy_from_eeprom (struct eth_device *dev);
47 void print_MAC (struct eth_device *dev);
48 int read_eeprom_reg (struct eth_device *dev, int reg);
49 void print_macaddr (struct eth_device *dev);
50 
51 int smc91111_eeprom (int argc, char *argv[])
52 {
53 	int c, i, j, done, line, reg, value, start, what;
54 	char input[50];
55 
56 	struct eth_device dev = {
57 		.iobase = CONFIG_SMC91111_BASE
58 	};
59 
60 	/* Print the ABI version */
61 	app_startup (argv);
62 	if (XF_VERSION != (int) get_version ()) {
63 		printf ("Expects ABI version %d\n", XF_VERSION);
64 		printf ("Actual U-Boot ABI version %d\n",
65 			(int) get_version ());
66 		printf ("Can't run\n\n");
67 		return (0);
68 	}
69 
70 	SMC91111_EEPROM_INIT();
71 
72 	if ((SMC_inw (&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
73 		printf ("Can't find SMSC91111\n");
74 		return (0);
75 	}
76 
77 	done = 0;
78 	what = UNKNOWN;
79 	printf ("\n");
80 	while (!done) {
81 		/* print the prompt */
82 		printf ("SMC91111> ");
83 		line = 0;
84 		i = 0;
85 		start = 1;
86 		while (!line) {
87 			/* Wait for a keystroke */
88 			while (!tstc ());
89 
90 			c = getc ();
91 			/* Make Uppercase */
92 			if (c >= 'Z')
93 				c -= ('a' - 'A');
94 			/* printf(" |%02x| ",c); */
95 
96 			switch (c) {
97 			case '\r':	/* Enter                */
98 			case '\n':
99 				input[i] = 0;
100 				puts ("\r\n");
101 				line = 1;
102 				break;
103 			case '\0':	/* nul                  */
104 				continue;
105 
106 			case 0x03:	/* ^C - break           */
107 				input[0] = 0;
108 				i = 0;
109 				line = 1;
110 				done = 1;
111 				break;
112 
113 			case 0x5F:
114 			case 0x08:	/* ^H  - backspace      */
115 			case 0x7F:	/* DEL - backspace      */
116 				if (i > 0) {
117 					puts ("\b \b");
118 					i--;
119 				}
120 				break;
121 			default:
122 				if (start) {
123 					if ((c == 'W') || (c == 'D')
124 					    || (c == 'M') || (c == 'C')
125 					    || (c == 'P')) {
126 						putc (c);
127 						input[i] = c;
128 						if (i <= 45)
129 							i++;
130 						start = 0;
131 					}
132 				} else {
133 					if ((c >= '0' && c <= '9')
134 					    || (c >= 'A' && c <= 'F')
135 					    || (c == 'E') || (c == 'M')
136 					    || (c == ' ')) {
137 						putc (c);
138 						input[i] = c;
139 						if (i <= 45)
140 							i++;
141 						break;
142 					}
143 				}
144 				break;
145 			}
146 		}
147 
148 		for (; i < 49; i++)
149 			input[i] = 0;
150 
151 		switch (input[0]) {
152 		case ('W'):
153 			/* Line should be w reg value */
154 			i = 0;
155 			reg = 0;
156 			value = 0;
157 			/* Skip to the next space or end) */
158 			while ((input[i] != ' ') && (input[i] != 0))
159 				i++;
160 
161 			if (input[i] != 0)
162 				i++;
163 
164 			/* Are we writing to EEPROM or MAC */
165 			switch (input[i]) {
166 			case ('E'):
167 				what = EEPROM;
168 				break;
169 			case ('M'):
170 				what = MAC;
171 				break;
172 			default:
173 				what = UNKNOWN;
174 				break;
175 			}
176 
177 			/* skip to the next space or end */
178 			while ((input[i] != ' ') && (input[i] != 0))
179 				i++;
180 			if (input[i] != 0)
181 				i++;
182 
183 			/* Find register to write into */
184 			j = 0;
185 			while ((input[i] != ' ') && (input[i] != 0)) {
186 				j = input[i] - 0x30;
187 				if (j >= 0xA) {
188 					j -= 0x07;
189 				}
190 				reg = (reg * 0x10) + j;
191 				i++;
192 			}
193 
194 			while ((input[i] != ' ') && (input[i] != 0))
195 				i++;
196 
197 			if (input[i] != 0)
198 				i++;
199 			else
200 				what = UNKNOWN;
201 
202 			/* Get the value to write */
203 			j = 0;
204 			while ((input[i] != ' ') && (input[i] != 0)) {
205 				j = input[i] - 0x30;
206 				if (j >= 0xA) {
207 					j -= 0x07;
208 				}
209 				value = (value * 0x10) + j;
210 				i++;
211 			}
212 
213 			switch (what) {
214 			case 1:
215 				printf ("Writing EEPROM register %02x with %04x\n", reg, value);
216 				write_eeprom_reg (&dev, value, reg);
217 				break;
218 			case 2:
219 				printf ("Writing MAC register bank %i, reg %02x with %04x\n", reg >> 4, reg & 0xE, value);
220 				SMC_SELECT_BANK (&dev, reg >> 4);
221 				SMC_outw (&dev, value, reg & 0xE);
222 				break;
223 			default:
224 				printf ("Wrong\n");
225 				break;
226 			}
227 			break;
228 		case ('D'):
229 			dump_eeprom (&dev);
230 			break;
231 		case ('M'):
232 			dump_reg (&dev);
233 			break;
234 		case ('C'):
235 			copy_from_eeprom (&dev);
236 			break;
237 		case ('P'):
238 			print_macaddr (&dev);
239 			break;
240 		default:
241 			break;
242 		}
243 
244 	}
245 
246 	return (0);
247 }
248 
249 void copy_from_eeprom (struct eth_device *dev)
250 {
251 	int i;
252 
253 	SMC_SELECT_BANK (dev, 1);
254 	SMC_outw (dev, (SMC_inw (dev, CTL_REG) & !CTL_EEPROM_SELECT) |
255 		CTL_RELOAD, CTL_REG);
256 	i = 100;
257 	while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --i)
258 		udelay (100);
259 	if (i == 0) {
260 		printf ("Timeout Refreshing EEPROM registers\n");
261 	} else {
262 		printf ("EEPROM contents copied to MAC\n");
263 	}
264 
265 }
266 
267 void print_macaddr (struct eth_device *dev)
268 {
269 	int i, j, k, mac[6];
270 
271 	printf ("Current MAC Address in SMSC91111 ");
272 	SMC_SELECT_BANK (dev, 1);
273 	for (i = 0; i < 5; i++) {
274 		printf ("%02x:", SMC_inb (dev, ADDR0_REG + i));
275 	}
276 
277 	printf ("%02x\n", SMC_inb (dev, ADDR0_REG + 5));
278 
279 	i = 0;
280 	for (j = 0x20; j < 0x23; j++) {
281 		k = read_eeprom_reg (dev, j);
282 		mac[i] = k & 0xFF;
283 		i++;
284 		mac[i] = k >> 8;
285 		i++;
286 	}
287 
288 	printf ("Current MAC Address in EEPROM    ");
289 	for (i = 0; i < 5; i++)
290 		printf ("%02x:", mac[i]);
291 	printf ("%02x\n", mac[5]);
292 
293 }
294 void dump_eeprom (struct eth_device *dev)
295 {
296 	int j, k;
297 
298 	printf ("IOS2-0    ");
299 	for (j = 0; j < 8; j++) {
300 		printf ("%03x     ", j);
301 	}
302 	printf ("\n");
303 
304 	for (k = 0; k < 4; k++) {
305 		if (k == 0)
306 			printf ("CONFIG ");
307 		if (k == 1)
308 			printf ("BASE   ");
309 		if ((k == 2) || (k == 3))
310 			printf ("       ");
311 		for (j = 0; j < 0x20; j += 4) {
312 			printf ("%02x:%04x ", j + k,
313 				read_eeprom_reg (dev, j + k));
314 		}
315 		printf ("\n");
316 	}
317 
318 	for (j = 0x20; j < 0x40; j++) {
319 		if ((j & 0x07) == 0)
320 			printf ("\n");
321 		printf ("%02x:%04x ", j, read_eeprom_reg (dev, j));
322 	}
323 	printf ("\n");
324 
325 }
326 
327 int read_eeprom_reg (struct eth_device *dev, int reg)
328 {
329 	int timeout;
330 
331 	SMC_SELECT_BANK (dev, 2);
332 	SMC_outw (dev, reg, PTR_REG);
333 
334 	SMC_SELECT_BANK (dev, 1);
335 	SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
336 		CTL_RELOAD, CTL_REG);
337 	timeout = 100;
338 	while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
339 		udelay (100);
340 	if (timeout == 0) {
341 		printf ("Timeout Reading EEPROM register %02x\n", reg);
342 		return 0;
343 	}
344 
345 	return SMC_inw (dev, GP_REG);
346 
347 }
348 
349 int write_eeprom_reg (struct eth_device *dev, int value, int reg)
350 {
351 	int timeout;
352 
353 	SMC_SELECT_BANK (dev, 2);
354 	SMC_outw (dev, reg, PTR_REG);
355 
356 	SMC_SELECT_BANK (dev, 1);
357 	SMC_outw (dev, value, GP_REG);
358 	SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
359 		CTL_STORE, CTL_REG);
360 	timeout = 100;
361 	while ((SMC_inw (dev, CTL_REG) & CTL_STORE) && --timeout)
362 		udelay (100);
363 	if (timeout == 0) {
364 		printf ("Timeout Writing EEPROM register %02x\n", reg);
365 		return 0;
366 	}
367 
368 	return 1;
369 
370 }
371 
372 void dump_reg (struct eth_device *dev)
373 {
374 	int i, j;
375 
376 	printf ("    ");
377 	for (j = 0; j < 4; j++) {
378 		printf ("Bank%i ", j);
379 	}
380 	printf ("\n");
381 	for (i = 0; i < 0xF; i += 2) {
382 		printf ("%02x  ", i);
383 		for (j = 0; j < 4; j++) {
384 			SMC_SELECT_BANK (dev, j);
385 			printf ("%04x  ", SMC_inw (dev, i));
386 		}
387 		printf ("\n");
388 	}
389 }
390