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