tricorder-eeprom.c 5.8 KB

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