1 /* 2 * smc911x_eeprom.c - EEPROM interface to SMC911x parts. 3 * Only tested on SMSC9118 though ... 4 * 5 * Copyright 2004-2009 Analog Devices Inc. 6 * 7 * Licensed under the GPL-2 or later. 8 * 9 * Based on smc91111_eeprom.c which: 10 * Heavily borrowed from the following peoples GPL'ed software: 11 * - Wolfgang Denk, DENX Software Engineering, wd@denx.de 12 * Das U-boot 13 * - Ladislav Michl ladis@linux-mips.org 14 * A rejected patch on the U-Boot mailing list 15 */ 16 17 #include <common.h> 18 #include <exports.h> 19 20 /* the smc911x.h gets base addr through eth_device' iobase */ 21 struct eth_device { 22 const char *name; 23 unsigned long iobase; 24 void *priv; 25 }; 26 #include "../drivers/net/smc911x.h" 27 28 /** 29 * smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?) 30 */ 31 static int smsc_ctrlc(void) 32 { 33 return (tstc() && getc() == 0x03); 34 } 35 36 /** 37 * usage - dump usage information 38 */ 39 static void usage(void) 40 { 41 puts( 42 "MAC/EEPROM Commands:\n" 43 " P : Print the MAC addresses\n" 44 " D : Dump the EEPROM contents\n" 45 " M : Dump the MAC contents\n" 46 " C : Copy the MAC address from the EEPROM to the MAC\n" 47 " W : Write a register in the EEPROM or in the MAC\n" 48 " Q : Quit\n" 49 "\n" 50 "Some commands take arguments:\n" 51 " W <E|M> <register> <value>\n" 52 " E: EEPROM M: MAC\n" 53 ); 54 } 55 56 /** 57 * dump_regs - dump the MAC registers 58 * 59 * Registers 0x00 - 0x50 are FIFOs. The 0x50+ are the control registers 60 * and they're all 32bits long. 0xB8+ are reserved, so don't bother. 61 */ 62 static void dump_regs(struct eth_device *dev) 63 { 64 u8 i, j = 0; 65 for (i = 0x50; i < 0xB8; i += sizeof(u32)) 66 printf("%02x: 0x%08x %c", i, 67 smc911x_reg_read(dev, i), 68 (j++ % 2 ? '\n' : ' ')); 69 } 70 71 /** 72 * do_eeprom_cmd - handle eeprom communication 73 */ 74 static int do_eeprom_cmd(struct eth_device *dev, int cmd, u8 reg) 75 { 76 if (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) { 77 printf("eeprom_cmd: busy at start (E2P_CMD = 0x%08x)\n", 78 smc911x_reg_read(dev, E2P_CMD)); 79 return -1; 80 } 81 82 smc911x_reg_write(dev, E2P_CMD, E2P_CMD_EPC_BUSY | cmd | reg); 83 84 while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) 85 if (smsc_ctrlc()) { 86 printf("eeprom_cmd: timeout (E2P_CMD = 0x%08x)\n", 87 smc911x_reg_read(dev, E2P_CMD)); 88 return -1; 89 } 90 91 return 0; 92 } 93 94 /** 95 * read_eeprom_reg - read specified register in EEPROM 96 */ 97 static u8 read_eeprom_reg(struct eth_device *dev, u8 reg) 98 { 99 int ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ, reg); 100 return (ret ? : smc911x_reg_read(dev, E2P_DATA)); 101 } 102 103 /** 104 * write_eeprom_reg - write specified value into specified register in EEPROM 105 */ 106 static int write_eeprom_reg(struct eth_device *dev, u8 value, u8 reg) 107 { 108 int ret; 109 110 /* enable erasing/writing */ 111 ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN, reg); 112 if (ret) 113 goto done; 114 115 /* erase the eeprom reg */ 116 ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE, reg); 117 if (ret) 118 goto done; 119 120 /* write the eeprom reg */ 121 smc911x_reg_write(dev, E2P_DATA, value); 122 ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE, reg); 123 if (ret) 124 goto done; 125 126 /* disable erasing/writing */ 127 ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWDS, reg); 128 129 done: 130 return ret; 131 } 132 133 /** 134 * skip_space - find first non-whitespace in given pointer 135 */ 136 static char *skip_space(char *buf) 137 { 138 while (buf[0] == ' ' || buf[0] == '\t') 139 ++buf; 140 return buf; 141 } 142 143 /** 144 * write_stuff - handle writing of MAC registers / eeprom 145 */ 146 static void write_stuff(struct eth_device *dev, char *line) 147 { 148 char dest; 149 char *endp; 150 u8 reg; 151 u32 value; 152 153 /* Skip over the "W " part of the command */ 154 line = skip_space(line + 1); 155 156 /* Figure out destination */ 157 switch (line[0]) { 158 case 'E': 159 case 'M': 160 dest = line[0]; 161 break; 162 default: 163 invalid_usage: 164 printf("ERROR: Invalid write usage\n"); 165 usage(); 166 return; 167 } 168 169 /* Get the register to write */ 170 line = skip_space(line + 1); 171 reg = simple_strtoul(line, &endp, 16); 172 if (line == endp) 173 goto invalid_usage; 174 175 /* Get the value to write */ 176 line = skip_space(endp); 177 value = simple_strtoul(line, &endp, 16); 178 if (line == endp) 179 goto invalid_usage; 180 181 /* Check for trailing cruft */ 182 line = skip_space(endp); 183 if (line[0]) 184 goto invalid_usage; 185 186 /* Finally, execute the command */ 187 if (dest == 'E') { 188 printf("Writing EEPROM register %02x with %02x\n", reg, value); 189 write_eeprom_reg(dev, value, reg); 190 } else { 191 printf("Writing MAC register %02x with %08x\n", reg, value); 192 smc911x_reg_write(dev, reg, value); 193 } 194 } 195 196 /** 197 * copy_from_eeprom - copy MAC address in eeprom to address registers 198 */ 199 static void copy_from_eeprom(struct eth_device *dev) 200 { 201 ulong addrl = 202 read_eeprom_reg(dev, 0x01) | 203 read_eeprom_reg(dev, 0x02) << 8 | 204 read_eeprom_reg(dev, 0x03) << 16 | 205 read_eeprom_reg(dev, 0x04) << 24; 206 ulong addrh = 207 read_eeprom_reg(dev, 0x05) | 208 read_eeprom_reg(dev, 0x06) << 8; 209 smc911x_set_mac_csr(dev, ADDRL, addrl); 210 smc911x_set_mac_csr(dev, ADDRH, addrh); 211 puts("EEPROM contents copied to MAC\n"); 212 } 213 214 /** 215 * print_macaddr - print MAC address registers and MAC address in eeprom 216 */ 217 static void print_macaddr(struct eth_device *dev) 218 { 219 puts("Current MAC Address in MAC: "); 220 ulong addrl = smc911x_get_mac_csr(dev, ADDRL); 221 ulong addrh = smc911x_get_mac_csr(dev, ADDRH); 222 printf("%02x:%02x:%02x:%02x:%02x:%02x\n", 223 (u8)(addrl), (u8)(addrl >> 8), (u8)(addrl >> 16), 224 (u8)(addrl >> 24), (u8)(addrh), (u8)(addrh >> 8)); 225 226 puts("Current MAC Address in EEPROM: "); 227 int i; 228 for (i = 1; i < 6; ++i) 229 printf("%02x:", read_eeprom_reg(dev, i)); 230 printf("%02x\n", read_eeprom_reg(dev, i)); 231 } 232 233 /** 234 * dump_eeprom - dump the whole content of the EEPROM 235 */ 236 static void dump_eeprom(struct eth_device *dev) 237 { 238 int i; 239 puts("EEPROM:\n"); 240 for (i = 0; i < 7; ++i) 241 printf("%02x: 0x%02x\n", i, read_eeprom_reg(dev, i)); 242 } 243 244 /** 245 * smc911x_init - get the MAC/EEPROM up and ready for use 246 */ 247 static int smc911x_init(struct eth_device *dev) 248 { 249 /* See if there is anything there */ 250 if (!smc911x_detect_chip(dev)) 251 return 1; 252 253 smc911x_reset(dev); 254 255 /* Make sure we set EEDIO/EECLK to the EEPROM */ 256 if (smc911x_reg_read(dev, GPIO_CFG) & GPIO_CFG_EEPR_EN) { 257 while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) 258 if (smsc_ctrlc()) { 259 printf("init: timeout (E2P_CMD = 0x%08x)\n", 260 smc911x_reg_read(dev, E2P_CMD)); 261 return 1; 262 } 263 smc911x_reg_write(dev, GPIO_CFG, 264 smc911x_reg_read(dev, GPIO_CFG) & ~GPIO_CFG_EEPR_EN); 265 } 266 267 return 0; 268 } 269 270 /** 271 * getline - consume a line of input and handle some escape sequences 272 */ 273 static char *getline(void) 274 { 275 static char buffer[100]; 276 char c; 277 size_t i; 278 279 i = 0; 280 while (1) { 281 buffer[i] = '\0'; 282 while (!tstc()) 283 continue; 284 285 c = getc(); 286 /* Convert to uppercase */ 287 if (c >= 'a' && c <= 'z') 288 c -= ('a' - 'A'); 289 290 switch (c) { 291 case '\r': /* Enter/Return key */ 292 case '\n': 293 puts("\n"); 294 return buffer; 295 296 case 0x03: /* ^C - break */ 297 return NULL; 298 299 case 0x5F: 300 case 0x08: /* ^H - backspace */ 301 case 0x7F: /* DEL - backspace */ 302 if (i) { 303 puts("\b \b"); 304 i--; 305 } 306 break; 307 308 default: 309 /* Ignore control characters */ 310 if (c < 0x20) 311 break; 312 /* Queue up all other characters */ 313 buffer[i++] = c; 314 printf("%c", c); 315 break; 316 } 317 } 318 } 319 320 /** 321 * smc911x_eeprom - our application's main() function 322 */ 323 int smc911x_eeprom(int argc, char *argv[]) 324 { 325 /* Avoid initializing on stack as gcc likes to call memset() */ 326 struct eth_device dev; 327 dev.name = __func__; 328 dev.iobase = CONFIG_SMC911X_BASE; 329 330 /* Print the ABI version */ 331 app_startup(argv); 332 if (XF_VERSION != get_version()) { 333 printf("Expects ABI version %d\n", XF_VERSION); 334 printf("Actual U-Boot ABI version %lu\n", get_version()); 335 printf("Can't run\n\n"); 336 return 1; 337 } 338 339 /* Initialize the MAC/EEPROM somewhat */ 340 puts("\n"); 341 if (smc911x_init(&dev)) 342 return 1; 343 344 /* Dump helpful usage information */ 345 puts("\n"); 346 usage(); 347 puts("\n"); 348 349 while (1) { 350 char *line; 351 352 /* Send the prompt and wait for a line */ 353 puts("eeprom> "); 354 line = getline(); 355 356 /* Got a ctrl+c */ 357 if (!line) 358 return 0; 359 360 /* Eat leading space */ 361 line = skip_space(line); 362 363 /* Empty line, try again */ 364 if (!line[0]) 365 continue; 366 367 /* Only accept 1 letter commands */ 368 if (line[0] && line[1] && line[1] != ' ' && line[1] != '\t') 369 goto unknown_cmd; 370 371 /* Now parse the command */ 372 switch (line[0]) { 373 case 'W': write_stuff(&dev, line); break; 374 case 'D': dump_eeprom(&dev); break; 375 case 'M': dump_regs(&dev); break; 376 case 'C': copy_from_eeprom(&dev); break; 377 case 'P': print_macaddr(&dev); break; 378 unknown_cmd: 379 default: puts("ERROR: Unknown command!\n\n"); 380 case '?': 381 case 'H': usage(); break; 382 case 'Q': return 0; 383 } 384 } 385 } 386