tricorder-eeprom.c 5.9 KB

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