mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-10-26 05:51:29 +01:00 
			
		
		
		
	Correct spelling of "U-Boot" shall be used in all written text (documentation, comments in source files etc.). Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Heiko Schocher <hs@denx.de> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Minkyu Kang <mk7.kang@samsung.com>
		
			
				
	
	
		
			373 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			373 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * (C) Copyright 2004
 | |
|  * Robin Getz rgetz@blacfin.uclinux.org
 | |
|  *
 | |
|  * SPDX-License-Identifier:	GPL-2.0+
 | |
|  *
 | |
|  * Heavily borrowed from the following peoples GPL'ed software:
 | |
|  *  - Wolfgang Denk, DENX Software Engineering, wd@denx.de
 | |
|  *       Das U-Boot
 | |
|  *  - Ladislav Michl ladis@linux-mips.org
 | |
|  *       A rejected patch on the U-Boot mailing list
 | |
|  */
 | |
| 
 | |
| #include <common.h>
 | |
| #include <exports.h>
 | |
| #include "../drivers/net/smc91111.h"
 | |
| 
 | |
| #ifndef SMC91111_EEPROM_INIT
 | |
| # define SMC91111_EEPROM_INIT()
 | |
| #endif
 | |
| 
 | |
| #define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE
 | |
| #define EEPROM		0x1
 | |
| #define MAC		0x2
 | |
| #define UNKNOWN		0x4
 | |
| 
 | |
| void dump_reg (struct eth_device *dev);
 | |
| void dump_eeprom (struct eth_device *dev);
 | |
| int write_eeprom_reg (struct eth_device *dev, int value, int reg);
 | |
| void copy_from_eeprom (struct eth_device *dev);
 | |
| void print_MAC (struct eth_device *dev);
 | |
| int read_eeprom_reg (struct eth_device *dev, int reg);
 | |
| void print_macaddr (struct eth_device *dev);
 | |
| 
 | |
| int smc91111_eeprom (int argc, char * const argv[])
 | |
| {
 | |
| 	int c, i, j, done, line, reg, value, start, what;
 | |
| 	char input[50];
 | |
| 
 | |
| 	struct eth_device dev;
 | |
| 	dev.iobase = CONFIG_SMC91111_BASE;
 | |
| 
 | |
| 	/* Print the ABI version */
 | |
| 	app_startup (argv);
 | |
| 	if (XF_VERSION != (int) get_version ()) {
 | |
| 		printf ("Expects ABI version %d\n", XF_VERSION);
 | |
| 		printf ("Actual U-Boot ABI version %d\n",
 | |
| 			(int) get_version ());
 | |
| 		printf ("Can't run\n\n");
 | |
| 		return (0);
 | |
| 	}
 | |
| 
 | |
| 	SMC91111_EEPROM_INIT();
 | |
| 
 | |
| 	if ((SMC_inw (&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
 | |
| 		printf ("Can't find SMSC91111\n");
 | |
| 		return (0);
 | |
| 	}
 | |
| 
 | |
| 	done = 0;
 | |
| 	what = UNKNOWN;
 | |
| 	printf ("\n");
 | |
| 	while (!done) {
 | |
| 		/* print the prompt */
 | |
| 		printf ("SMC91111> ");
 | |
| 		line = 0;
 | |
| 		i = 0;
 | |
| 		start = 1;
 | |
| 		while (!line) {
 | |
| 			/* Wait for a keystroke */
 | |
| 			while (!tstc ());
 | |
| 
 | |
| 			c = getc ();
 | |
| 			/* Make Uppercase */
 | |
| 			if (c >= 'Z')
 | |
| 				c -= ('a' - 'A');
 | |
| 			/* printf(" |%02x| ",c); */
 | |
| 
 | |
| 			switch (c) {
 | |
| 			case '\r':	/* Enter                */
 | |
| 			case '\n':
 | |
| 				input[i] = 0;
 | |
| 				puts ("\r\n");
 | |
| 				line = 1;
 | |
| 				break;
 | |
| 			case '\0':	/* nul                  */
 | |
| 				continue;
 | |
| 
 | |
| 			case 0x03:	/* ^C - break           */
 | |
| 				input[0] = 0;
 | |
| 				i = 0;
 | |
| 				line = 1;
 | |
| 				done = 1;
 | |
| 				break;
 | |
| 
 | |
| 			case 0x5F:
 | |
| 			case 0x08:	/* ^H  - backspace      */
 | |
| 			case 0x7F:	/* DEL - backspace      */
 | |
| 				if (i > 0) {
 | |
| 					puts ("\b \b");
 | |
| 					i--;
 | |
| 				}
 | |
| 				break;
 | |
| 			default:
 | |
| 				if (start) {
 | |
| 					if ((c == 'W') || (c == 'D')
 | |
| 					    || (c == 'M') || (c == 'C')
 | |
| 					    || (c == 'P')) {
 | |
| 						putc (c);
 | |
| 						input[i] = c;
 | |
| 						if (i <= 45)
 | |
| 							i++;
 | |
| 						start = 0;
 | |
| 					}
 | |
| 				} else {
 | |
| 					if ((c >= '0' && c <= '9')
 | |
| 					    || (c >= 'A' && c <= 'F')
 | |
| 					    || (c == 'E') || (c == 'M')
 | |
| 					    || (c == ' ')) {
 | |
| 						putc (c);
 | |
| 						input[i] = c;
 | |
| 						if (i <= 45)
 | |
| 							i++;
 | |
| 						break;
 | |
| 					}
 | |
| 				}
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		for (; i < 49; i++)
 | |
| 			input[i] = 0;
 | |
| 
 | |
| 		switch (input[0]) {
 | |
| 		case ('W'):
 | |
| 			/* Line should be w reg value */
 | |
| 			i = 0;
 | |
| 			reg = 0;
 | |
| 			value = 0;
 | |
| 			/* Skip to the next space or end) */
 | |
| 			while ((input[i] != ' ') && (input[i] != 0))
 | |
| 				i++;
 | |
| 
 | |
| 			if (input[i] != 0)
 | |
| 				i++;
 | |
| 
 | |
| 			/* Are we writing to EEPROM or MAC */
 | |
| 			switch (input[i]) {
 | |
| 			case ('E'):
 | |
| 				what = EEPROM;
 | |
| 				break;
 | |
| 			case ('M'):
 | |
| 				what = MAC;
 | |
| 				break;
 | |
| 			default:
 | |
| 				what = UNKNOWN;
 | |
| 				break;
 | |
| 			}
 | |
| 
 | |
| 			/* skip to the next space or end */
 | |
| 			while ((input[i] != ' ') && (input[i] != 0))
 | |
| 				i++;
 | |
| 			if (input[i] != 0)
 | |
| 				i++;
 | |
| 
 | |
| 			/* Find register to write into */
 | |
| 			j = 0;
 | |
| 			while ((input[i] != ' ') && (input[i] != 0)) {
 | |
| 				j = input[i] - 0x30;
 | |
| 				if (j >= 0xA) {
 | |
| 					j -= 0x07;
 | |
| 				}
 | |
| 				reg = (reg * 0x10) + j;
 | |
| 				i++;
 | |
| 			}
 | |
| 
 | |
| 			while ((input[i] != ' ') && (input[i] != 0))
 | |
| 				i++;
 | |
| 
 | |
| 			if (input[i] != 0)
 | |
| 				i++;
 | |
| 			else
 | |
| 				what = UNKNOWN;
 | |
| 
 | |
| 			/* Get the value to write */
 | |
| 			j = 0;
 | |
| 			while ((input[i] != ' ') && (input[i] != 0)) {
 | |
| 				j = input[i] - 0x30;
 | |
| 				if (j >= 0xA) {
 | |
| 					j -= 0x07;
 | |
| 				}
 | |
| 				value = (value * 0x10) + j;
 | |
| 				i++;
 | |
| 			}
 | |
| 
 | |
| 			switch (what) {
 | |
| 			case 1:
 | |
| 				printf ("Writing EEPROM register %02x with %04x\n", reg, value);
 | |
| 				write_eeprom_reg (&dev, value, reg);
 | |
| 				break;
 | |
| 			case 2:
 | |
| 				printf ("Writing MAC register bank %i, reg %02x with %04x\n", reg >> 4, reg & 0xE, value);
 | |
| 				SMC_SELECT_BANK (&dev, reg >> 4);
 | |
| 				SMC_outw (&dev, value, reg & 0xE);
 | |
| 				break;
 | |
| 			default:
 | |
| 				printf ("Wrong\n");
 | |
| 				break;
 | |
| 			}
 | |
| 			break;
 | |
| 		case ('D'):
 | |
| 			dump_eeprom (&dev);
 | |
| 			break;
 | |
| 		case ('M'):
 | |
| 			dump_reg (&dev);
 | |
| 			break;
 | |
| 		case ('C'):
 | |
| 			copy_from_eeprom (&dev);
 | |
| 			break;
 | |
| 		case ('P'):
 | |
| 			print_macaddr (&dev);
 | |
| 			break;
 | |
| 		default:
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	return (0);
 | |
| }
 | |
| 
 | |
| void copy_from_eeprom (struct eth_device *dev)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	SMC_SELECT_BANK (dev, 1);
 | |
| 	SMC_outw (dev, (SMC_inw (dev, CTL_REG) & !CTL_EEPROM_SELECT) |
 | |
| 		CTL_RELOAD, CTL_REG);
 | |
| 	i = 100;
 | |
| 	while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --i)
 | |
| 		udelay (100);
 | |
| 	if (i == 0) {
 | |
| 		printf ("Timeout Refreshing EEPROM registers\n");
 | |
| 	} else {
 | |
| 		printf ("EEPROM contents copied to MAC\n");
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| void print_macaddr (struct eth_device *dev)
 | |
| {
 | |
| 	int i, j, k, mac[6];
 | |
| 
 | |
| 	printf ("Current MAC Address in SMSC91111 ");
 | |
| 	SMC_SELECT_BANK (dev, 1);
 | |
| 	for (i = 0; i < 5; i++) {
 | |
| 		printf ("%02x:", SMC_inb (dev, ADDR0_REG + i));
 | |
| 	}
 | |
| 
 | |
| 	printf ("%02x\n", SMC_inb (dev, ADDR0_REG + 5));
 | |
| 
 | |
| 	i = 0;
 | |
| 	for (j = 0x20; j < 0x23; j++) {
 | |
| 		k = read_eeprom_reg (dev, j);
 | |
| 		mac[i] = k & 0xFF;
 | |
| 		i++;
 | |
| 		mac[i] = k >> 8;
 | |
| 		i++;
 | |
| 	}
 | |
| 
 | |
| 	printf ("Current MAC Address in EEPROM    ");
 | |
| 	for (i = 0; i < 5; i++)
 | |
| 		printf ("%02x:", mac[i]);
 | |
| 	printf ("%02x\n", mac[5]);
 | |
| 
 | |
| }
 | |
| void dump_eeprom (struct eth_device *dev)
 | |
| {
 | |
| 	int j, k;
 | |
| 
 | |
| 	printf ("IOS2-0    ");
 | |
| 	for (j = 0; j < 8; j++) {
 | |
| 		printf ("%03x     ", j);
 | |
| 	}
 | |
| 	printf ("\n");
 | |
| 
 | |
| 	for (k = 0; k < 4; k++) {
 | |
| 		if (k == 0)
 | |
| 			printf ("CONFIG ");
 | |
| 		if (k == 1)
 | |
| 			printf ("BASE   ");
 | |
| 		if ((k == 2) || (k == 3))
 | |
| 			printf ("       ");
 | |
| 		for (j = 0; j < 0x20; j += 4) {
 | |
| 			printf ("%02x:%04x ", j + k,
 | |
| 				read_eeprom_reg (dev, j + k));
 | |
| 		}
 | |
| 		printf ("\n");
 | |
| 	}
 | |
| 
 | |
| 	for (j = 0x20; j < 0x40; j++) {
 | |
| 		if ((j & 0x07) == 0)
 | |
| 			printf ("\n");
 | |
| 		printf ("%02x:%04x ", j, read_eeprom_reg (dev, j));
 | |
| 	}
 | |
| 	printf ("\n");
 | |
| 
 | |
| }
 | |
| 
 | |
| int read_eeprom_reg (struct eth_device *dev, int reg)
 | |
| {
 | |
| 	int timeout;
 | |
| 
 | |
| 	SMC_SELECT_BANK (dev, 2);
 | |
| 	SMC_outw (dev, reg, PTR_REG);
 | |
| 
 | |
| 	SMC_SELECT_BANK (dev, 1);
 | |
| 	SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
 | |
| 		CTL_RELOAD, CTL_REG);
 | |
| 	timeout = 100;
 | |
| 	while ((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
 | |
| 		udelay (100);
 | |
| 	if (timeout == 0) {
 | |
| 		printf ("Timeout Reading EEPROM register %02x\n", reg);
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	return SMC_inw (dev, GP_REG);
 | |
| 
 | |
| }
 | |
| 
 | |
| int write_eeprom_reg (struct eth_device *dev, int value, int reg)
 | |
| {
 | |
| 	int timeout;
 | |
| 
 | |
| 	SMC_SELECT_BANK (dev, 2);
 | |
| 	SMC_outw (dev, reg, PTR_REG);
 | |
| 
 | |
| 	SMC_SELECT_BANK (dev, 1);
 | |
| 	SMC_outw (dev, value, GP_REG);
 | |
| 	SMC_outw (dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT |
 | |
| 		CTL_STORE, CTL_REG);
 | |
| 	timeout = 100;
 | |
| 	while ((SMC_inw (dev, CTL_REG) & CTL_STORE) && --timeout)
 | |
| 		udelay (100);
 | |
| 	if (timeout == 0) {
 | |
| 		printf ("Timeout Writing EEPROM register %02x\n", reg);
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	return 1;
 | |
| 
 | |
| }
 | |
| 
 | |
| void dump_reg (struct eth_device *dev)
 | |
| {
 | |
| 	int i, j;
 | |
| 
 | |
| 	printf ("    ");
 | |
| 	for (j = 0; j < 4; j++) {
 | |
| 		printf ("Bank%i ", j);
 | |
| 	}
 | |
| 	printf ("\n");
 | |
| 	for (i = 0; i < 0xF; i += 2) {
 | |
| 		printf ("%02x  ", i);
 | |
| 		for (j = 0; j < 4; j++) {
 | |
| 			SMC_SELECT_BANK (dev, j);
 | |
| 			printf ("%04x  ", SMC_inw (dev, i));
 | |
| 		}
 | |
| 		printf ("\n");
 | |
| 	}
 | |
| }
 |