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