tricorder-eeprom.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * (C) Copyright 2013
  3. * Corscience GmbH & Co. KG, <www.corscience.de>
  4. * Andreas Bießmann <andreas.biessmann@corscience.de>
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <common.h>
  9. #include <i2c.h>
  10. #include "tricorder-eeprom.h"
  11. static inline void warn_wrong_value(const char *msg, unsigned int a,
  12. unsigned int b)
  13. {
  14. printf("Expected EEPROM %s %08x, got %08x\n", msg, a, b);
  15. }
  16. static int handle_eeprom_v0(struct tricorder_eeprom *eeprom)
  17. {
  18. struct tricorder_eeprom_v0 {
  19. uint32_t magic;
  20. uint16_t length;
  21. uint16_t version;
  22. char board_name[TRICORDER_BOARD_NAME_LENGTH];
  23. char board_version[TRICORDER_BOARD_VERSION_LENGTH];
  24. char board_serial[TRICORDER_BOARD_SERIAL_LENGTH];
  25. uint32_t crc32;
  26. } __packed eepromv0;
  27. uint32_t crc;
  28. printf("Old EEPROM (v0), consider rewrite!\n");
  29. if (be16_to_cpu(eeprom->length) != sizeof(eepromv0)) {
  30. warn_wrong_value("length", sizeof(eepromv0),
  31. be16_to_cpu(eeprom->length));
  32. return 1;
  33. }
  34. memcpy(&eepromv0, eeprom, sizeof(eepromv0));
  35. crc = crc32(0L, (unsigned char *)&eepromv0,
  36. sizeof(eepromv0) - sizeof(eepromv0.crc32));
  37. if (be32_to_cpu(eepromv0.crc32) != crc) {
  38. warn_wrong_value("CRC", be32_to_cpu(eepromv0.crc32),
  39. crc);
  40. return 1;
  41. }
  42. /* Ok the content is correct, do the conversion */
  43. memset(eeprom->interface_version, 0x0,
  44. TRICORDER_INTERFACE_VERSION_LENGTH);
  45. crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
  46. eeprom->crc32 = cpu_to_be32(crc);
  47. return 0;
  48. }
  49. static int handle_eeprom_v1(struct tricorder_eeprom *eeprom)
  50. {
  51. uint32_t crc;
  52. if (be16_to_cpu(eeprom->length) != TRICORDER_EEPROM_SIZE) {
  53. warn_wrong_value("length", TRICORDER_EEPROM_SIZE,
  54. be16_to_cpu(eeprom->length));
  55. return 1;
  56. }
  57. crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
  58. if (be32_to_cpu(eeprom->crc32) != crc) {
  59. warn_wrong_value("CRC", be32_to_cpu(eeprom->crc32), crc);
  60. return 1;
  61. }
  62. return 0;
  63. }
  64. int tricorder_get_eeprom(int addr, struct tricorder_eeprom *eeprom)
  65. {
  66. #ifdef CONFIG_SYS_EEPROM_BUS_NUM
  67. unsigned int bus = i2c_get_bus_num();
  68. i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
  69. #endif
  70. memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
  71. i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
  72. #ifdef CONFIG_SYS_EEPROM_BUS_NUM
  73. i2c_set_bus_num(bus);
  74. #endif
  75. if (be32_to_cpu(eeprom->magic) != TRICORDER_EEPROM_MAGIC) {
  76. warn_wrong_value("magic", TRICORDER_EEPROM_MAGIC,
  77. be32_to_cpu(eeprom->magic));
  78. return 1;
  79. }
  80. switch (be16_to_cpu(eeprom->version)) {
  81. case 0:
  82. return handle_eeprom_v0(eeprom);
  83. case 1:
  84. return handle_eeprom_v1(eeprom);
  85. default:
  86. warn_wrong_value("version", TRICORDER_EEPROM_VERSION,
  87. be16_to_cpu(eeprom->version));
  88. return 1;
  89. }
  90. }
  91. #if !defined(CONFIG_SPL)
  92. int tricorder_eeprom_read(unsigned devaddr)
  93. {
  94. struct tricorder_eeprom eeprom;
  95. int ret = tricorder_get_eeprom(devaddr, &eeprom);
  96. if (ret)
  97. return ret;
  98. printf("Board type: %.*s\n",
  99. sizeof(eeprom.board_name), eeprom.board_name);
  100. printf("Board version: %.*s\n",
  101. sizeof(eeprom.board_version), eeprom.board_version);
  102. printf("Board serial: %.*s\n",
  103. sizeof(eeprom.board_serial), eeprom.board_serial);
  104. printf("Board interface version: %.*s\n",
  105. sizeof(eeprom.interface_version),
  106. eeprom.interface_version);
  107. return ret;
  108. }
  109. int tricorder_eeprom_write(unsigned devaddr, const char *name,
  110. const char *version, const char *serial, const char *interface)
  111. {
  112. struct tricorder_eeprom eeprom, eeprom_verify;
  113. size_t length;
  114. uint32_t crc;
  115. int ret;
  116. unsigned char *p;
  117. int i;
  118. #ifdef CONFIG_SYS_EEPROM_BUS_NUM
  119. unsigned int bus;
  120. #endif
  121. memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
  122. memset(eeprom_verify, 0, TRICORDER_EEPROM_SIZE);
  123. eeprom.magic = cpu_to_be32(TRICORDER_EEPROM_MAGIC);
  124. eeprom.length = cpu_to_be16(TRICORDER_EEPROM_SIZE);
  125. eeprom.version = cpu_to_be16(TRICORDER_EEPROM_VERSION);
  126. length = min(sizeof(eeprom.board_name), strlen(name));
  127. strncpy(eeprom.board_name, name, length);
  128. length = min(sizeof(eeprom.board_version), strlen(version));
  129. strncpy(eeprom.board_version, version, length);
  130. length = min(sizeof(eeprom.board_serial), strlen(serial));
  131. strncpy(eeprom.board_serial, serial, length);
  132. if (interface) {
  133. length = min(sizeof(eeprom.interface_version),
  134. strlen(interface));
  135. strncpy(eeprom.interface_version, interface, length);
  136. }
  137. crc = crc32(0L, (unsigned char *)&eeprom, TRICORDER_EEPROM_CRC_SIZE);
  138. eeprom.crc32 = cpu_to_be32(crc);
  139. #if defined(DEBUG)
  140. puts("Tricorder EEPROM content:\n");
  141. print_buffer(0, &eeprom, 1, sizeof(eeprom), 16);
  142. #endif
  143. #ifdef CONFIG_SYS_EEPROM_BUS_NUM
  144. bus = i2c_get_bus_num();
  145. i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
  146. #endif
  147. /* do page write to the eeprom */
  148. for (i = 0, p = (unsigned char *)&eeprom;
  149. i < sizeof(eeprom);
  150. i += 32, p += 32) {
  151. ret = i2c_write(devaddr, i, CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
  152. p, min(sizeof(eeprom) - i, 32));
  153. if (ret)
  154. break;
  155. udelay(5000); /* 5ms write cycle timing */
  156. }
  157. ret = i2c_read(devaddr, 0, 2, (unsigned char *)&eeprom_verify,
  158. TRICORDER_EEPROM_SIZE);
  159. if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
  160. printf("Tricorder: Could not verify EEPROM content!\n");
  161. ret = 1;
  162. }
  163. #ifdef CONFIG_SYS_EEPROM_BUS_NUM
  164. i2c_set_bus_num(bus);
  165. #endif
  166. return ret;
  167. }
  168. int do_tricorder_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  169. {
  170. if (argc == 3) {
  171. ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
  172. eeprom_init();
  173. if (strcmp(argv[1], "read") == 0) {
  174. int rcode;
  175. rcode = tricorder_eeprom_read(dev_addr);
  176. return rcode;
  177. }
  178. } else if (argc == 6 || argc == 7) {
  179. ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
  180. char *name = argv[3];
  181. char *version = argv[4];
  182. char *serial = argv[5];
  183. char *interface = NULL;
  184. eeprom_init();
  185. if (argc == 7)
  186. interface = argv[6];
  187. if (strcmp(argv[1], "write") == 0) {
  188. int rcode;
  189. rcode = tricorder_eeprom_write(dev_addr, name, version,
  190. serial, interface);
  191. return rcode;
  192. }
  193. }
  194. return CMD_RET_USAGE;
  195. }
  196. U_BOOT_CMD(
  197. tricordereeprom, 7, 1, do_tricorder_eeprom,
  198. "Tricorder EEPROM",
  199. "read devaddr\n"
  200. " - read Tricorder EEPROM at devaddr and print content\n"
  201. "tricordereeprom write devaddr name version serial [interface]\n"
  202. " - write Tricorder EEPROM at devaddr with 'name', 'version'"
  203. "and 'serial'\n"
  204. " optional add an HW interface parameter"
  205. );
  206. #endif /* CONFIG_SPL */