ds4510.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. * Copyright 2008 Extreme Engineering Solutions, Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * Version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  16. * MA 02111-1307 USA
  17. */
  18. /*
  19. * Driver for DS4510, a CPU supervisor with integrated EEPROM, SRAM,
  20. * and 4 programmable non-volatile GPIO pins.
  21. */
  22. #include <common.h>
  23. #include <i2c.h>
  24. #include <command.h>
  25. #include <ds4510.h>
  26. /* Default to an address that hopefully won't corrupt other i2c devices */
  27. #ifndef CONFIG_SYS_I2C_DS4510_ADDR
  28. #define CONFIG_SYS_I2C_DS4510_ADDR (~0)
  29. #endif
  30. enum {
  31. DS4510_CMD_INFO,
  32. DS4510_CMD_DEVICE,
  33. DS4510_CMD_NV,
  34. DS4510_CMD_RSTDELAY,
  35. DS4510_CMD_OUTPUT,
  36. DS4510_CMD_INPUT,
  37. DS4510_CMD_PULLUP,
  38. DS4510_CMD_EEPROM,
  39. DS4510_CMD_SEEPROM,
  40. DS4510_CMD_SRAM,
  41. };
  42. /*
  43. * Write to DS4510, taking page boundaries into account
  44. */
  45. int ds4510_mem_write(uint8_t chip, int offset, uint8_t *buf, int count)
  46. {
  47. int wrlen;
  48. int i = 0;
  49. do {
  50. wrlen = DS4510_EEPROM_PAGE_SIZE -
  51. DS4510_EEPROM_PAGE_OFFSET(offset);
  52. if (count < wrlen)
  53. wrlen = count;
  54. if (i2c_write(chip, offset, 1, &buf[i], wrlen))
  55. return -1;
  56. /*
  57. * This delay isn't needed for SRAM writes but shouldn't delay
  58. * things too much, so do it unconditionally for simplicity
  59. */
  60. udelay(DS4510_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
  61. count -= wrlen;
  62. offset += wrlen;
  63. i += wrlen;
  64. } while (count > 0);
  65. return 0;
  66. }
  67. /*
  68. * General read from DS4510
  69. */
  70. int ds4510_mem_read(uint8_t chip, int offset, uint8_t *buf, int count)
  71. {
  72. return i2c_read(chip, offset, 1, buf, count);
  73. }
  74. /*
  75. * Write SEE bit in config register.
  76. * nv = 0 - Writes to SEEPROM registers behave like EEPROM
  77. * nv = 1 - Writes to SEEPROM registers behave like SRAM
  78. */
  79. int ds4510_see_write(uint8_t chip, uint8_t nv)
  80. {
  81. uint8_t data;
  82. if (i2c_read(chip, DS4510_CFG, 1, &data, 1))
  83. return -1;
  84. if (nv) /* Treat SEEPROM bits as EEPROM */
  85. data &= ~DS4510_CFG_SEE;
  86. else /* Treat SEEPROM bits as SRAM */
  87. data |= DS4510_CFG_SEE;
  88. return ds4510_mem_write(chip, DS4510_CFG, &data, 1);
  89. }
  90. /*
  91. * Write de-assertion of reset signal delay
  92. */
  93. int ds4510_rstdelay_write(uint8_t chip, uint8_t delay)
  94. {
  95. uint8_t data;
  96. if (i2c_read(chip, DS4510_RSTDELAY, 1, &data, 1))
  97. return -1;
  98. data &= ~DS4510_RSTDELAY_MASK;
  99. data |= delay & DS4510_RSTDELAY_MASK;
  100. return ds4510_mem_write(chip, DS4510_RSTDELAY, &data, 1);
  101. }
  102. /*
  103. * Write pullup characteristics of IO pins
  104. */
  105. int ds4510_pullup_write(uint8_t chip, uint8_t val)
  106. {
  107. val &= DS4510_IO_MASK;
  108. return ds4510_mem_write(chip, DS4510_PULLUP, (uint8_t *)&val, 1);
  109. }
  110. /*
  111. * Read pullup characteristics of IO pins
  112. */
  113. int ds4510_pullup_read(uint8_t chip)
  114. {
  115. uint8_t val;
  116. if (i2c_read(chip, DS4510_PULLUP, 1, &val, 1))
  117. return -1;
  118. return val & DS4510_IO_MASK;
  119. }
  120. /*
  121. * Write drive level of IO pins
  122. */
  123. int ds4510_gpio_write(uint8_t chip, uint8_t val)
  124. {
  125. uint8_t data;
  126. int i;
  127. for (i = 0; i < DS4510_NUM_IO; i++) {
  128. if (i2c_read(chip, DS4510_IO0 - i, 1, &data, 1))
  129. return -1;
  130. if (val & (0x1 << i))
  131. data |= 0x1;
  132. else
  133. data &= ~0x1;
  134. if (ds4510_mem_write(chip, DS4510_IO0 - i, &data, 1))
  135. return -1;
  136. }
  137. return 0;
  138. }
  139. /*
  140. * Read drive level of IO pins
  141. */
  142. int ds4510_gpio_read(uint8_t chip)
  143. {
  144. uint8_t data;
  145. int val = 0;
  146. int i;
  147. for (i = 0; i < DS4510_NUM_IO; i++) {
  148. if (i2c_read(chip, DS4510_IO0 - i, 1, &data, 1))
  149. return -1;
  150. if (data & 1)
  151. val |= (1 << i);
  152. }
  153. return val;
  154. }
  155. /*
  156. * Read physical level of IO pins
  157. */
  158. int ds4510_gpio_read_val(uint8_t chip)
  159. {
  160. uint8_t val;
  161. if (i2c_read(chip, DS4510_IO_STATUS, 1, &val, 1))
  162. return -1;
  163. return val & DS4510_IO_MASK;
  164. }
  165. #ifdef CONFIG_CMD_DS4510
  166. #ifdef CONFIG_CMD_DS4510_INFO
  167. /*
  168. * Display DS4510 information
  169. */
  170. static int ds4510_info(uint8_t chip)
  171. {
  172. int i;
  173. int tmp;
  174. uint8_t data;
  175. printf("DS4510 @ 0x%x:\n\n", chip);
  176. if (i2c_read(chip, DS4510_RSTDELAY, 1, &data, 1))
  177. return -1;
  178. printf("rstdelay = 0x%x\n\n", data & DS4510_RSTDELAY_MASK);
  179. if (i2c_read(chip, DS4510_CFG, 1, &data, 1))
  180. return -1;
  181. printf("config = 0x%x\n", data);
  182. printf(" /ready = %d\n", data & DS4510_CFG_READY ? 1 : 0);
  183. printf(" trip pt = %d\n", data & DS4510_CFG_TRIP_POINT ? 1 : 0);
  184. printf(" rst sts = %d\n", data & DS4510_CFG_RESET ? 1 : 0);
  185. printf(" /see = %d\n", data & DS4510_CFG_SEE ? 1 : 0);
  186. printf(" swrst = %d\n\n", data & DS4510_CFG_SWRST ? 1 : 0);
  187. printf("gpio pins: 3210\n");
  188. printf("---------------\n");
  189. printf("pullup ");
  190. tmp = ds4510_pullup_read(chip);
  191. if (tmp == -1)
  192. return tmp;
  193. for (i = DS4510_NUM_IO - 1; i >= 0; i--)
  194. printf("%d", (tmp & (1 << i)) ? 1 : 0);
  195. printf("\n");
  196. printf("driven ");
  197. tmp = ds4510_gpio_read(chip);
  198. if (tmp == -1)
  199. return -1;
  200. for (i = DS4510_NUM_IO - 1; i >= 0; i--)
  201. printf("%d", (tmp & (1 << i)) ? 1 : 0);
  202. printf("\n");
  203. printf("read ");
  204. tmp = ds4510_gpio_read_val(chip);
  205. if (tmp == -1)
  206. return -1;
  207. for (i = DS4510_NUM_IO - 1; i >= 0; i--)
  208. printf("%d", (tmp & (1 << i)) ? 1 : 0);
  209. printf("\n");
  210. return 0;
  211. }
  212. #endif /* CONFIG_CMD_DS4510_INFO */
  213. cmd_tbl_t cmd_ds4510[] = {
  214. U_BOOT_CMD_MKENT(device, 3, 0, (void *)DS4510_CMD_DEVICE, "", ""),
  215. U_BOOT_CMD_MKENT(nv, 3, 0, (void *)DS4510_CMD_NV, "", ""),
  216. U_BOOT_CMD_MKENT(output, 4, 0, (void *)DS4510_CMD_OUTPUT, "", ""),
  217. U_BOOT_CMD_MKENT(input, 3, 0, (void *)DS4510_CMD_INPUT, "", ""),
  218. U_BOOT_CMD_MKENT(pullup, 4, 0, (void *)DS4510_CMD_PULLUP, "", ""),
  219. #ifdef CONFIG_CMD_DS4510_INFO
  220. U_BOOT_CMD_MKENT(info, 2, 0, (void *)DS4510_CMD_INFO, "", ""),
  221. #endif
  222. #ifdef CONFIG_CMD_DS4510_RST
  223. U_BOOT_CMD_MKENT(rstdelay, 3, 0, (void *)DS4510_CMD_RSTDELAY, "", ""),
  224. #endif
  225. #ifdef CONFIG_CMD_DS4510_MEM
  226. U_BOOT_CMD_MKENT(eeprom, 6, 0, (void *)DS4510_CMD_EEPROM, "", ""),
  227. U_BOOT_CMD_MKENT(seeprom, 6, 0, (void *)DS4510_CMD_SEEPROM, "", ""),
  228. U_BOOT_CMD_MKENT(sram, 6, 0, (void *)DS4510_CMD_SRAM, "", ""),
  229. #endif
  230. };
  231. int do_ds4510(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  232. {
  233. static uint8_t chip = CONFIG_SYS_I2C_DS4510_ADDR;
  234. cmd_tbl_t *c;
  235. ulong ul_arg2 = 0;
  236. ulong ul_arg3 = 0;
  237. int tmp;
  238. #ifdef CONFIG_CMD_DS4510_MEM
  239. ulong addr;
  240. ulong off;
  241. ulong cnt;
  242. int end;
  243. int (*rw_func)(uint8_t, int, uint8_t *, int);
  244. #endif
  245. c = find_cmd_tbl(argv[1], cmd_ds4510, ARRAY_SIZE(cmd_ds4510));
  246. /* All commands but "device" require 'maxargs' arguments */
  247. if (!c || !((argc == (c->maxargs)) ||
  248. (((int)c->cmd == DS4510_CMD_DEVICE) &&
  249. (argc == (c->maxargs - 1))))) {
  250. cmd_usage(cmdtp);
  251. return 1;
  252. }
  253. /* arg2 used as chip addr and pin number */
  254. if (argc > 2)
  255. ul_arg2 = simple_strtoul(argv[2], NULL, 16);
  256. /* arg3 used as output/pullup value */
  257. if (argc > 3)
  258. ul_arg3 = simple_strtoul(argv[3], NULL, 16);
  259. switch ((int)c->cmd) {
  260. case DS4510_CMD_DEVICE:
  261. if (argc == 3)
  262. chip = ul_arg2;
  263. printf("Current device address: 0x%x\n", chip);
  264. return 0;
  265. case DS4510_CMD_NV:
  266. return ds4510_see_write(chip, ul_arg2);
  267. case DS4510_CMD_OUTPUT:
  268. tmp = ds4510_gpio_read(chip);
  269. if (tmp == -1)
  270. return -1;
  271. if (ul_arg3)
  272. tmp |= (1 << ul_arg2);
  273. else
  274. tmp &= ~(1 << ul_arg2);
  275. return ds4510_gpio_write(chip, tmp);
  276. case DS4510_CMD_INPUT:
  277. tmp = ds4510_gpio_read_val(chip);
  278. if (tmp == -1)
  279. return -1;
  280. return (tmp & (1 << ul_arg2)) != 0;
  281. case DS4510_CMD_PULLUP:
  282. tmp = ds4510_pullup_read(chip);
  283. if (tmp == -1)
  284. return -1;
  285. if (ul_arg3)
  286. tmp |= (1 << ul_arg2);
  287. else
  288. tmp &= ~(1 << ul_arg2);
  289. return ds4510_pullup_write(chip, tmp);
  290. #ifdef CONFIG_CMD_DS4510_INFO
  291. case DS4510_CMD_INFO:
  292. return ds4510_info(chip);
  293. #endif
  294. #ifdef CONFIG_CMD_DS4510_RST
  295. case DS4510_CMD_RSTDELAY:
  296. return ds4510_rstdelay_write(chip, ul_arg2);
  297. #endif
  298. #ifdef CONFIG_CMD_DS4510_MEM
  299. case DS4510_CMD_EEPROM:
  300. end = DS4510_EEPROM + DS4510_EEPROM_SIZE;
  301. off = DS4510_EEPROM;
  302. break;
  303. case DS4510_CMD_SEEPROM:
  304. end = DS4510_SEEPROM + DS4510_SEEPROM_SIZE;
  305. off = DS4510_SEEPROM;
  306. break;
  307. case DS4510_CMD_SRAM:
  308. end = DS4510_SRAM + DS4510_SRAM_SIZE;
  309. off = DS4510_SRAM;
  310. break;
  311. #endif
  312. default:
  313. /* We should never get here... */
  314. return 1;
  315. }
  316. #ifdef CONFIG_CMD_DS4510_MEM
  317. /* Only eeprom, seeprom, and sram commands should make it here */
  318. if (strcmp(argv[2], "read") == 0) {
  319. rw_func = ds4510_mem_read;
  320. } else if (strcmp(argv[2], "write") == 0) {
  321. rw_func = ds4510_mem_write;
  322. } else {
  323. cmd_usage(cmdtp);
  324. return 1;
  325. }
  326. addr = simple_strtoul(argv[3], NULL, 16);
  327. off += simple_strtoul(argv[4], NULL, 16);
  328. cnt = simple_strtoul(argv[5], NULL, 16);
  329. if ((off + cnt) > end) {
  330. printf("ERROR: invalid len\n");
  331. return -1;
  332. }
  333. return rw_func(chip, off, (uint8_t *)addr, cnt);
  334. #endif
  335. }
  336. U_BOOT_CMD(
  337. ds4510, 6, 1, do_ds4510,
  338. "ds4510 - ds4510 eeprom/seeprom/sram/gpio access\n",
  339. "device [dev]\n"
  340. " - show or set current device address\n"
  341. #ifdef CONFIG_CMD_DS4510_INFO
  342. "ds4510 info\n"
  343. " - display ds4510 info\n"
  344. #endif
  345. "ds4510 output pin 0|1\n"
  346. " - set pin low or high-Z\n"
  347. "ds4510 input pin\n"
  348. " - read value of pin\n"
  349. "ds4510 pullup pin 0|1\n"
  350. " - disable/enable pullup on specified pin\n"
  351. "ds4510 nv 0|1\n"
  352. " - make gpio and seeprom writes volatile/non-volatile\n"
  353. #ifdef CONFIG_CMD_DS4510_RST
  354. "ds4510 rstdelay 0-3\n"
  355. " - set reset output delay\n"
  356. #endif
  357. #ifdef CONFIG_CMD_DS4510_MEM
  358. "ds4510 eeprom read addr off cnt\n"
  359. "ds4510 eeprom write addr off cnt\n"
  360. " - read/write 'cnt' bytes at EEPROM offset 'off'\n"
  361. "ds4510 seeprom read addr off cnt\n"
  362. "ds4510 seeprom write addr off cnt\n"
  363. " - read/write 'cnt' bytes at SRAM-shadowed EEPROM offset 'off'\n"
  364. "ds4510 sram read addr off cnt\n"
  365. "ds4510 sram write addr off cnt\n"
  366. " - read/write 'cnt' bytes at SRAM offset 'off'\n"
  367. #endif
  368. );
  369. #endif /* CONFIG_CMD_DS4510 */