/* * (C) Copyright 2004 * Robin Getz rgetz@blacfin.uclinux.org * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * 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" #define SMC_BASE_ADDRESS CONFIG_SMC91111_BASE #define EEPROM 0x1; #define MAC 0x2; #define UNKNOWN 0x4; void dump_reg (void); void dump_eeprom (void); int write_eeprom_reg (int, int); void copy_from_eeprom (void); void print_MAC (void); int read_eeprom_reg (int); void print_macaddr (void); int smc91111_eeprom (int argc, char *argv[]) { int c, i, j, done, line, reg, value, start, what; char input[50]; /* 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); } asm ("p2.h = 0xFFC0;"); asm ("p2.l = 0x0730;"); asm ("r0 = 0x01;"); asm ("w[p2] = r0;"); asm ("ssync;"); asm ("p2.h = 0xffc0;"); asm ("p2.l = 0x0708;"); asm ("r0 = 0x01;"); asm ("w[p2] = r0;"); asm ("ssync;"); if ((SMC_inw (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 (value, reg); break; case 2: printf ("Writing MAC register bank %i, reg %02x with %04x\n", reg >> 4, reg & 0xE, value); SMC_SELECT_BANK (reg >> 4); SMC_outw (value, reg & 0xE); break; default: printf ("Wrong\n"); break; } break; case ('D'): dump_eeprom (); break; case ('M'): dump_reg (); break; case ('C'): copy_from_eeprom (); break; case ('P'): print_macaddr (); break; default: break; } } return (0); } void copy_from_eeprom (void) { int i; SMC_SELECT_BANK (1); SMC_outw ((SMC_inw (CTL_REG) & !CTL_EEPROM_SELECT) | CTL_RELOAD, CTL_REG); i = 100; while ((SMC_inw (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 (void) { int i, j, k, mac[6]; printf ("Current MAC Address in SMSC91111 "); SMC_SELECT_BANK (1); for (i = 0; i < 5; i++) { printf ("%02x:", SMC_inb (ADDR0_REG + i)); } printf ("%02x\n", SMC_inb (ADDR0_REG + 5)); i = 0; for (j = 0x20; j < 0x23; j++) { k = read_eeprom_reg (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 (void) { 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 (j + k)); } printf ("\n"); } for (j = 0x20; j < 0x40; j++) { if ((j & 0x07) == 0) printf ("\n"); printf ("%02x:%04x ", j, read_eeprom_reg (j)); } printf ("\n"); } int read_eeprom_reg (int reg) { int timeout; SMC_SELECT_BANK (2); SMC_outw (reg, PTR_REG); SMC_SELECT_BANK (1); SMC_outw (SMC_inw (CTL_REG) | CTL_EEPROM_SELECT | CTL_RELOAD, CTL_REG); timeout = 100; while ((SMC_inw (CTL_REG) & CTL_RELOAD) && --timeout) udelay (100); if (timeout == 0) { printf ("Timeout Reading EEPROM register %02x\n", reg); return 0; } return SMC_inw (GP_REG); } int write_eeprom_reg (int value, int reg) { int timeout; SMC_SELECT_BANK (2); SMC_outw (reg, PTR_REG); SMC_SELECT_BANK (1); SMC_outw (value, GP_REG); SMC_outw (SMC_inw (CTL_REG) | CTL_EEPROM_SELECT | CTL_STORE, CTL_REG); timeout = 100; while ((SMC_inw (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 (void) { 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 (j); printf ("%04x ", SMC_inw (i)); } printf ("\n"); } }