smc911x_eeprom.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  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. #include <common.h>
  17. #include <console.h>
  18. #include <exports.h>
  19. #include <net.h>
  20. #include <linux/ctype.h>
  21. #include <linux/types.h>
  22. #include "../drivers/net/smc911x.h"
  23. #define DRIVERNAME "smc911x"
  24. #if defined (CONFIG_SMC911X_32_BIT) && \
  25. defined (CONFIG_SMC911X_16_BIT)
  26. #error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \
  27. CONFIG_SMC911X_16_BIT shall be set"
  28. #endif
  29. struct chip_id {
  30. u16 id;
  31. char *name;
  32. };
  33. static const struct chip_id chip_ids[] = {
  34. { CHIP_89218, "LAN89218" },
  35. { CHIP_9115, "LAN9115" },
  36. { CHIP_9116, "LAN9116" },
  37. { CHIP_9117, "LAN9117" },
  38. { CHIP_9118, "LAN9118" },
  39. { CHIP_9211, "LAN9211" },
  40. { CHIP_9215, "LAN9215" },
  41. { CHIP_9216, "LAN9216" },
  42. { CHIP_9217, "LAN9217" },
  43. { CHIP_9218, "LAN9218" },
  44. { CHIP_9220, "LAN9220" },
  45. { CHIP_9221, "LAN9221" },
  46. { 0, NULL },
  47. };
  48. #if defined (CONFIG_SMC911X_32_BIT)
  49. static u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
  50. {
  51. return *(volatile u32*)(dev->iobase + offset);
  52. }
  53. static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val)
  54. {
  55. *(volatile u32*)(dev->iobase + offset) = val;
  56. }
  57. #elif defined (CONFIG_SMC911X_16_BIT)
  58. static u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
  59. {
  60. volatile u16 *addr_16 = (u16 *)(dev->iobase + offset);
  61. return (*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16);
  62. }
  63. static void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val)
  64. {
  65. *(volatile u16 *)(dev->iobase + offset) = (u16)val;
  66. *(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16);
  67. }
  68. #else
  69. #error "SMC911X: undefined bus width"
  70. #endif /* CONFIG_SMC911X_16_BIT */
  71. static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg)
  72. {
  73. while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
  74. ;
  75. smc911x_reg_write(dev, MAC_CSR_CMD,
  76. MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
  77. while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
  78. ;
  79. return smc911x_reg_read(dev, MAC_CSR_DATA);
  80. }
  81. static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data)
  82. {
  83. while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
  84. ;
  85. smc911x_reg_write(dev, MAC_CSR_DATA, data);
  86. smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
  87. while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
  88. ;
  89. }
  90. static int smc911x_detect_chip(struct eth_device *dev)
  91. {
  92. unsigned long val, i;
  93. val = smc911x_reg_read(dev, BYTE_TEST);
  94. if (val == 0xffffffff) {
  95. /* Special case -- no chip present */
  96. return -1;
  97. } else if (val != 0x87654321) {
  98. printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
  99. return -1;
  100. }
  101. val = smc911x_reg_read(dev, ID_REV) >> 16;
  102. for (i = 0; chip_ids[i].id != 0; i++) {
  103. if (chip_ids[i].id == val) break;
  104. }
  105. if (!chip_ids[i].id) {
  106. printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);
  107. return -1;
  108. }
  109. dev->priv = (void *)&chip_ids[i];
  110. return 0;
  111. }
  112. static void smc911x_reset(struct eth_device *dev)
  113. {
  114. int timeout;
  115. /*
  116. * Take out of PM setting first
  117. * Device is already wake up if PMT_CTRL_READY bit is set
  118. */
  119. if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) {
  120. /* Write to the bytetest will take out of powerdown */
  121. smc911x_reg_write(dev, BYTE_TEST, 0x0);
  122. timeout = 10;
  123. while (timeout-- &&
  124. !(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY))
  125. udelay(10);
  126. if (timeout < 0) {
  127. printf(DRIVERNAME
  128. ": timeout waiting for PM restore\n");
  129. return;
  130. }
  131. }
  132. /* Disable interrupts */
  133. smc911x_reg_write(dev, INT_EN, 0);
  134. smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST);
  135. timeout = 1000;
  136. while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
  137. udelay(10);
  138. if (timeout < 0) {
  139. printf(DRIVERNAME ": reset timeout\n");
  140. return;
  141. }
  142. /* Reset the FIFO level and flow control settings */
  143. smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN);
  144. smc911x_reg_write(dev, AFC_CFG, 0x0050287F);
  145. /* Set to LED outputs */
  146. smc911x_reg_write(dev, GPIO_CFG, 0x70070000);
  147. }
  148. /**
  149. * smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?)
  150. */
  151. static int smsc_ctrlc(void)
  152. {
  153. return (tstc() && getc() == 0x03);
  154. }
  155. /**
  156. * usage - dump usage information
  157. */
  158. static void usage(void)
  159. {
  160. puts(
  161. "MAC/EEPROM Commands:\n"
  162. " P : Print the MAC addresses\n"
  163. " D : Dump the EEPROM contents\n"
  164. " M : Dump the MAC contents\n"
  165. " C : Copy the MAC address from the EEPROM to the MAC\n"
  166. " W : Write a register in the EEPROM or in the MAC\n"
  167. " Q : Quit\n"
  168. "\n"
  169. "Some commands take arguments:\n"
  170. " W <E|M> <register> <value>\n"
  171. " E: EEPROM M: MAC\n"
  172. );
  173. }
  174. /**
  175. * dump_regs - dump the MAC registers
  176. *
  177. * Registers 0x00 - 0x50 are FIFOs. The 0x50+ are the control registers
  178. * and they're all 32bits long. 0xB8+ are reserved, so don't bother.
  179. */
  180. static void dump_regs(struct eth_device *dev)
  181. {
  182. u8 i, j = 0;
  183. for (i = 0x50; i < 0xB8; i += sizeof(u32))
  184. printf("%02x: 0x%08x %c", i,
  185. smc911x_reg_read(dev, i),
  186. (j++ % 2 ? '\n' : ' '));
  187. }
  188. /**
  189. * do_eeprom_cmd - handle eeprom communication
  190. */
  191. static int do_eeprom_cmd(struct eth_device *dev, int cmd, u8 reg)
  192. {
  193. if (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY) {
  194. printf("eeprom_cmd: busy at start (E2P_CMD = 0x%08x)\n",
  195. smc911x_reg_read(dev, E2P_CMD));
  196. return -1;
  197. }
  198. smc911x_reg_write(dev, E2P_CMD, E2P_CMD_EPC_BUSY | cmd | reg);
  199. while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
  200. if (smsc_ctrlc()) {
  201. printf("eeprom_cmd: timeout (E2P_CMD = 0x%08x)\n",
  202. smc911x_reg_read(dev, E2P_CMD));
  203. return -1;
  204. }
  205. return 0;
  206. }
  207. /**
  208. * read_eeprom_reg - read specified register in EEPROM
  209. */
  210. static u8 read_eeprom_reg(struct eth_device *dev, u8 reg)
  211. {
  212. int ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ, reg);
  213. return (ret ? : smc911x_reg_read(dev, E2P_DATA));
  214. }
  215. /**
  216. * write_eeprom_reg - write specified value into specified register in EEPROM
  217. */
  218. static int write_eeprom_reg(struct eth_device *dev, u8 value, u8 reg)
  219. {
  220. int ret;
  221. /* enable erasing/writing */
  222. ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN, reg);
  223. if (ret)
  224. goto done;
  225. /* erase the eeprom reg */
  226. ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE, reg);
  227. if (ret)
  228. goto done;
  229. /* write the eeprom reg */
  230. smc911x_reg_write(dev, E2P_DATA, value);
  231. ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE, reg);
  232. if (ret)
  233. goto done;
  234. /* disable erasing/writing */
  235. ret = do_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWDS, reg);
  236. done:
  237. return ret;
  238. }
  239. /**
  240. * skip_space - find first non-whitespace in given pointer
  241. */
  242. static char *skip_space(char *buf)
  243. {
  244. while (isblank(buf[0]))
  245. ++buf;
  246. return buf;
  247. }
  248. /**
  249. * write_stuff - handle writing of MAC registers / eeprom
  250. */
  251. static void write_stuff(struct eth_device *dev, char *line)
  252. {
  253. char dest;
  254. char *endp;
  255. u8 reg;
  256. u32 value;
  257. /* Skip over the "W " part of the command */
  258. line = skip_space(line + 1);
  259. /* Figure out destination */
  260. switch (line[0]) {
  261. case 'E':
  262. case 'M':
  263. dest = line[0];
  264. break;
  265. default:
  266. invalid_usage:
  267. printf("ERROR: Invalid write usage\n");
  268. usage();
  269. return;
  270. }
  271. /* Get the register to write */
  272. line = skip_space(line + 1);
  273. reg = simple_strtoul(line, &endp, 16);
  274. if (line == endp)
  275. goto invalid_usage;
  276. /* Get the value to write */
  277. line = skip_space(endp);
  278. value = simple_strtoul(line, &endp, 16);
  279. if (line == endp)
  280. goto invalid_usage;
  281. /* Check for trailing cruft */
  282. line = skip_space(endp);
  283. if (line[0])
  284. goto invalid_usage;
  285. /* Finally, execute the command */
  286. if (dest == 'E') {
  287. printf("Writing EEPROM register %02x with %02x\n", reg, value);
  288. write_eeprom_reg(dev, value, reg);
  289. } else {
  290. printf("Writing MAC register %02x with %08x\n", reg, value);
  291. smc911x_reg_write(dev, reg, value);
  292. }
  293. }
  294. /**
  295. * copy_from_eeprom - copy MAC address in eeprom to address registers
  296. */
  297. static void copy_from_eeprom(struct eth_device *dev)
  298. {
  299. ulong addrl =
  300. read_eeprom_reg(dev, 0x01) |
  301. read_eeprom_reg(dev, 0x02) << 8 |
  302. read_eeprom_reg(dev, 0x03) << 16 |
  303. read_eeprom_reg(dev, 0x04) << 24;
  304. ulong addrh =
  305. read_eeprom_reg(dev, 0x05) |
  306. read_eeprom_reg(dev, 0x06) << 8;
  307. smc911x_set_mac_csr(dev, ADDRL, addrl);
  308. smc911x_set_mac_csr(dev, ADDRH, addrh);
  309. puts("EEPROM contents copied to MAC\n");
  310. }
  311. /**
  312. * print_macaddr - print MAC address registers and MAC address in eeprom
  313. */
  314. static void print_macaddr(struct eth_device *dev)
  315. {
  316. puts("Current MAC Address in MAC: ");
  317. ulong addrl = smc911x_get_mac_csr(dev, ADDRL);
  318. ulong addrh = smc911x_get_mac_csr(dev, ADDRH);
  319. printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
  320. (u8)(addrl), (u8)(addrl >> 8), (u8)(addrl >> 16),
  321. (u8)(addrl >> 24), (u8)(addrh), (u8)(addrh >> 8));
  322. puts("Current MAC Address in EEPROM: ");
  323. int i;
  324. for (i = 1; i < 6; ++i)
  325. printf("%02x:", read_eeprom_reg(dev, i));
  326. printf("%02x\n", read_eeprom_reg(dev, i));
  327. }
  328. /**
  329. * dump_eeprom - dump the whole content of the EEPROM
  330. */
  331. static void dump_eeprom(struct eth_device *dev)
  332. {
  333. int i;
  334. puts("EEPROM:\n");
  335. for (i = 0; i < 7; ++i)
  336. printf("%02x: 0x%02x\n", i, read_eeprom_reg(dev, i));
  337. }
  338. /**
  339. * smc911x_init - get the MAC/EEPROM up and ready for use
  340. */
  341. static int smc911x_init(struct eth_device *dev)
  342. {
  343. /* See if there is anything there */
  344. if (smc911x_detect_chip(dev))
  345. return 1;
  346. smc911x_reset(dev);
  347. /* Make sure we set EEDIO/EECLK to the EEPROM */
  348. if (smc911x_reg_read(dev, GPIO_CFG) & GPIO_CFG_EEPR_EN) {
  349. while (smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
  350. if (smsc_ctrlc()) {
  351. printf("init: timeout (E2P_CMD = 0x%08x)\n",
  352. smc911x_reg_read(dev, E2P_CMD));
  353. return 1;
  354. }
  355. smc911x_reg_write(dev, GPIO_CFG,
  356. smc911x_reg_read(dev, GPIO_CFG) & ~GPIO_CFG_EEPR_EN);
  357. }
  358. return 0;
  359. }
  360. /**
  361. * getline - consume a line of input and handle some escape sequences
  362. */
  363. static char *getline(void)
  364. {
  365. static char buffer[100];
  366. char c;
  367. size_t i;
  368. i = 0;
  369. while (1) {
  370. buffer[i] = '\0';
  371. while (!tstc())
  372. continue;
  373. c = getc();
  374. /* Convert to uppercase */
  375. if (c >= 'a' && c <= 'z')
  376. c -= ('a' - 'A');
  377. switch (c) {
  378. case '\r': /* Enter/Return key */
  379. case '\n':
  380. puts("\n");
  381. return buffer;
  382. case 0x03: /* ^C - break */
  383. return NULL;
  384. case 0x5F:
  385. case 0x08: /* ^H - backspace */
  386. case 0x7F: /* DEL - backspace */
  387. if (i) {
  388. puts("\b \b");
  389. i--;
  390. }
  391. break;
  392. default:
  393. /* Ignore control characters */
  394. if (c < 0x20)
  395. break;
  396. /* Queue up all other characters */
  397. buffer[i++] = c;
  398. printf("%c", c);
  399. break;
  400. }
  401. }
  402. }
  403. /**
  404. * smc911x_eeprom - our application's main() function
  405. */
  406. int smc911x_eeprom(int argc, char *const argv[])
  407. {
  408. /* Avoid initializing on stack as gcc likes to call memset() */
  409. struct eth_device dev;
  410. dev.iobase = CONFIG_SMC911X_BASE;
  411. /* Print the ABI version */
  412. app_startup(argv);
  413. if (XF_VERSION != get_version()) {
  414. printf("Expects ABI version %d\n", XF_VERSION);
  415. printf("Actual U-Boot ABI version %lu\n", get_version());
  416. printf("Can't run\n\n");
  417. return 1;
  418. }
  419. /* Initialize the MAC/EEPROM somewhat */
  420. puts("\n");
  421. if (smc911x_init(&dev))
  422. return 1;
  423. /* Dump helpful usage information */
  424. puts("\n");
  425. usage();
  426. puts("\n");
  427. while (1) {
  428. char *line;
  429. /* Send the prompt and wait for a line */
  430. puts("eeprom> ");
  431. line = getline();
  432. /* Got a ctrl+c */
  433. if (!line)
  434. return 0;
  435. /* Eat leading space */
  436. line = skip_space(line);
  437. /* Empty line, try again */
  438. if (!line[0])
  439. continue;
  440. /* Only accept 1 letter commands */
  441. if (line[0] && line[1] && !isblank(line[1]))
  442. goto unknown_cmd;
  443. /* Now parse the command */
  444. switch (line[0]) {
  445. case 'W': write_stuff(&dev, line); break;
  446. case 'D': dump_eeprom(&dev); break;
  447. case 'M': dump_regs(&dev); break;
  448. case 'C': copy_from_eeprom(&dev); break;
  449. case 'P': print_macaddr(&dev); break;
  450. unknown_cmd:
  451. default: puts("ERROR: Unknown command!\n\n");
  452. case '?':
  453. case 'H': usage(); break;
  454. case 'Q': return 0;
  455. }
  456. }
  457. }