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