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