eeprom.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2014 Gateworks Corporation
  4. * Author: Tim Harvey <tharvey@gateworks.com>
  5. */
  6. #include <common.h>
  7. #include <command.h>
  8. #include <errno.h>
  9. #include <hexdump.h>
  10. #include <i2c.h>
  11. #include <log.h>
  12. #include <malloc.h>
  13. #include <asm/bitops.h>
  14. #include <linux/delay.h>
  15. #include "gsc.h"
  16. #include "ventana_eeprom.h"
  17. /* read ventana EEPROM, check for validity, and return baseboard type */
  18. int
  19. read_eeprom(int bus, struct ventana_board_info *info)
  20. {
  21. int i;
  22. int chksum;
  23. char baseboard;
  24. int type;
  25. unsigned char *buf = (unsigned char *)info;
  26. memset(info, 0, sizeof(*info));
  27. /*
  28. * On a board with a missing/depleted backup battery for GSC, the
  29. * board may be ready to probe the GSC before its firmware is
  30. * running. We will wait here indefinately for the GSC/EEPROM.
  31. */
  32. while (1) {
  33. if (0 == i2c_set_bus_num(bus) &&
  34. 0 == i2c_probe(GSC_EEPROM_ADDR))
  35. break;
  36. mdelay(1);
  37. }
  38. /* read eeprom config section */
  39. mdelay(10);
  40. if (gsc_i2c_read(GSC_EEPROM_ADDR, 0x00, 1, buf, sizeof(*info))) {
  41. puts("EEPROM: Failed to read EEPROM\n");
  42. return GW_UNKNOWN;
  43. }
  44. /* sanity checks */
  45. if (info->model[0] != 'G' || info->model[1] != 'W') {
  46. puts("EEPROM: Invalid Model in EEPROM\n");
  47. print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf,
  48. sizeof(*info));
  49. return GW_UNKNOWN;
  50. }
  51. /* validate checksum */
  52. for (chksum = 0, i = 0; i < sizeof(*info)-2; i++)
  53. chksum += buf[i];
  54. if ((info->chksum[0] != chksum>>8) ||
  55. (info->chksum[1] != (chksum&0xff))) {
  56. puts("EEPROM: Failed EEPROM checksum\n");
  57. print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf,
  58. sizeof(*info));
  59. return GW_UNKNOWN;
  60. }
  61. /* original GW5400-A prototype */
  62. baseboard = info->model[3];
  63. if (strncasecmp((const char *)info->model, "GW5400-A", 8) == 0)
  64. baseboard = '0';
  65. type = GW_UNKNOWN;
  66. switch (baseboard) {
  67. case '0': /* original GW5400-A prototype */
  68. type = GW54proto;
  69. break;
  70. case '1':
  71. type = GW51xx;
  72. break;
  73. case '2':
  74. type = GW52xx;
  75. break;
  76. case '3':
  77. type = GW53xx;
  78. break;
  79. case '4':
  80. type = GW54xx;
  81. break;
  82. case '5':
  83. if (info->model[4] == '1') {
  84. type = GW551x;
  85. break;
  86. } else if (info->model[4] == '2') {
  87. type = GW552x;
  88. break;
  89. } else if (info->model[4] == '3') {
  90. type = GW553x;
  91. break;
  92. }
  93. break;
  94. case '6':
  95. if (info->model[4] == '0')
  96. type = GW560x;
  97. break;
  98. case '9':
  99. if (info->model[4] == '0' && info->model[5] == '1')
  100. type = GW5901;
  101. else if (info->model[4] == '0' && info->model[5] == '2')
  102. type = GW5902;
  103. else if (info->model[4] == '0' && info->model[5] == '3')
  104. type = GW5903;
  105. else if (info->model[4] == '0' && info->model[5] == '4')
  106. type = GW5904;
  107. else if (info->model[4] == '0' && info->model[5] == '5')
  108. type = GW5905;
  109. else if (info->model[4] == '0' && info->model[5] == '6')
  110. type = GW5906;
  111. else if (info->model[4] == '0' && info->model[5] == '7')
  112. type = GW5907;
  113. else if (info->model[4] == '0' && info->model[5] == '8')
  114. type = GW5908;
  115. else if (info->model[4] == '0' && info->model[5] == '9')
  116. type = GW5909;
  117. else if (info->model[4] == '1' && info->model[5] == '0')
  118. type = GW5910;
  119. else if (info->model[4] == '1' && info->model[5] == '2')
  120. type = GW5912;
  121. else if (info->model[4] == '1' && info->model[5] == '3')
  122. type = GW5913;
  123. break;
  124. default:
  125. printf("EEPROM: Unknown model in EEPROM: %s\n", info->model);
  126. print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf,
  127. sizeof(*info));
  128. break;
  129. }
  130. return type;
  131. }
  132. /* list of config bits that the bootloader will remove from dtb if not set */
  133. struct ventana_eeprom_config econfig[] = {
  134. { "eth0", "ethernet0", EECONFIG_ETH0 },
  135. { "usb0", NULL, EECONFIG_USB0 },
  136. { "usb1", NULL, EECONFIG_USB1 },
  137. { "mmc0", NULL, EECONFIG_SD0 },
  138. { "mmc1", NULL, EECONFIG_SD1 },
  139. { "mmc2", NULL, EECONFIG_SD2 },
  140. { "mmc3", NULL, EECONFIG_SD3 },
  141. { /* Sentinel */ }
  142. };
  143. #if defined(CONFIG_CMD_EECONFIG) && !defined(CONFIG_SPL_BUILD)
  144. static struct ventana_eeprom_config *get_config(const char *name)
  145. {
  146. struct ventana_eeprom_config *cfg = econfig;
  147. while (cfg->name) {
  148. if (0 == strcmp(name, cfg->name))
  149. return cfg;
  150. cfg++;
  151. }
  152. return NULL;
  153. }
  154. static u8 econfig_bytes[sizeof(ventana_info.config)];
  155. static int econfig_init = -1;
  156. static int do_econfig(struct cmd_tbl *cmdtp, int flag, int argc,
  157. char *const argv[])
  158. {
  159. struct ventana_eeprom_config *cfg;
  160. struct ventana_board_info *info = &ventana_info;
  161. int i;
  162. if (argc < 2)
  163. return CMD_RET_USAGE;
  164. /* initialize */
  165. if (econfig_init != 1) {
  166. memcpy(econfig_bytes, info->config, sizeof(econfig_bytes));
  167. econfig_init = 1;
  168. }
  169. /* list configs */
  170. if ((strncmp(argv[1], "list", 4) == 0)) {
  171. cfg = econfig;
  172. while (cfg->name) {
  173. printf("%s: %d\n", cfg->name,
  174. test_bit(cfg->bit, econfig_bytes) ? 1 : 0);
  175. cfg++;
  176. }
  177. }
  178. /* save */
  179. else if ((strncmp(argv[1], "save", 4) == 0)) {
  180. unsigned char *buf = (unsigned char *)info;
  181. int chksum;
  182. /* calculate new checksum */
  183. memcpy(info->config, econfig_bytes, sizeof(econfig_bytes));
  184. for (chksum = 0, i = 0; i < sizeof(*info)-2; i++)
  185. chksum += buf[i];
  186. debug("old chksum:0x%04x\n",
  187. (info->chksum[0] << 8) | info->chksum[1]);
  188. debug("new chksum:0x%04x\n", chksum);
  189. info->chksum[0] = chksum >> 8;
  190. info->chksum[1] = chksum & 0xff;
  191. /* write new config data */
  192. if (gsc_i2c_write(GSC_EEPROM_ADDR, info->config - (u8 *)info,
  193. 1, econfig_bytes, sizeof(econfig_bytes))) {
  194. printf("EEPROM: Failed updating config\n");
  195. return CMD_RET_FAILURE;
  196. }
  197. /* write new config data */
  198. if (gsc_i2c_write(GSC_EEPROM_ADDR, info->chksum - (u8 *)info,
  199. 1, info->chksum, 2)) {
  200. printf("EEPROM: Failed updating checksum\n");
  201. return CMD_RET_FAILURE;
  202. }
  203. printf("Config saved to EEPROM\n");
  204. }
  205. /* get config */
  206. else if (argc == 2) {
  207. cfg = get_config(argv[1]);
  208. if (cfg) {
  209. printf("%s: %d\n", cfg->name,
  210. test_bit(cfg->bit, econfig_bytes) ? 1 : 0);
  211. } else {
  212. printf("invalid config: %s\n", argv[1]);
  213. return CMD_RET_FAILURE;
  214. }
  215. }
  216. /* set config */
  217. else if (argc == 3) {
  218. cfg = get_config(argv[1]);
  219. if (cfg) {
  220. if (simple_strtol(argv[2], NULL, 10)) {
  221. test_and_set_bit(cfg->bit, econfig_bytes);
  222. printf("Enabled %s\n", cfg->name);
  223. } else {
  224. test_and_clear_bit(cfg->bit, econfig_bytes);
  225. printf("Disabled %s\n", cfg->name);
  226. }
  227. } else {
  228. printf("invalid config: %s\n", argv[1]);
  229. return CMD_RET_FAILURE;
  230. }
  231. }
  232. else
  233. return CMD_RET_USAGE;
  234. return CMD_RET_SUCCESS;
  235. }
  236. U_BOOT_CMD(
  237. econfig, 3, 0, do_econfig,
  238. "EEPROM configuration",
  239. "list - list config\n"
  240. "save - save config to EEPROM\n"
  241. "<name> - get config 'name'\n"
  242. "<name> [0|1] - set config 'name' to value\n"
  243. );
  244. #endif /* CONFIG_CMD_EECONFIG */