/* * (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 #include #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"); } }