1
2
3
4
5
6
7
8#include <common.h>
9#include <i2c.h>
10
11#include "tricorder-eeprom.h"
12
13static 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
19static int handle_eeprom_v0(struct tricorder_eeprom *eeprom)
20{
21 struct tricorder_eeprom_v0 {
22 uint32_t magic;
23 uint16_t length;
24 uint16_t version;
25 char board_name[TRICORDER_BOARD_NAME_LENGTH];
26 char board_version[TRICORDER_BOARD_VERSION_LENGTH];
27 char board_serial[TRICORDER_BOARD_SERIAL_LENGTH];
28 uint32_t crc32;
29 } __packed eepromv0;
30 uint32_t crc;
31
32 printf("Old EEPROM (v0), consider rewrite!\n");
33
34 if (be16_to_cpu(eeprom->length) != sizeof(eepromv0)) {
35 warn_wrong_value("length", sizeof(eepromv0),
36 be16_to_cpu(eeprom->length));
37 return 1;
38 }
39
40 memcpy(&eepromv0, eeprom, sizeof(eepromv0));
41
42 crc = crc32(0L, (unsigned char *)&eepromv0,
43 sizeof(eepromv0) - sizeof(eepromv0.crc32));
44 if (be32_to_cpu(eepromv0.crc32) != crc) {
45 warn_wrong_value("CRC", be32_to_cpu(eepromv0.crc32),
46 crc);
47 return 1;
48 }
49
50
51 memset(eeprom->interface_version, 0x0,
52 TRICORDER_INTERFACE_VERSION_LENGTH);
53 crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
54 eeprom->crc32 = cpu_to_be32(crc);
55
56 return 0;
57}
58
59static int handle_eeprom_v1(struct tricorder_eeprom *eeprom)
60{
61 uint32_t crc;
62
63 if (be16_to_cpu(eeprom->length) != TRICORDER_EEPROM_SIZE) {
64 warn_wrong_value("length", TRICORDER_EEPROM_SIZE,
65 be16_to_cpu(eeprom->length));
66 return 1;
67 }
68
69 crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
70 if (be32_to_cpu(eeprom->crc32) != crc) {
71 warn_wrong_value("CRC", be32_to_cpu(eeprom->crc32), crc);
72 return 1;
73 }
74
75 return 0;
76}
77
78int tricorder_get_eeprom(int addr, struct tricorder_eeprom *eeprom)
79{
80#ifdef CONFIG_SYS_EEPROM_BUS_NUM
81 unsigned int bus = i2c_get_bus_num();
82 i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
83#endif
84
85 memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
86
87 i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
88#ifdef CONFIG_SYS_EEPROM_BUS_NUM
89 i2c_set_bus_num(bus);
90#endif
91
92 if (be32_to_cpu(eeprom->magic) != TRICORDER_EEPROM_MAGIC) {
93 warn_wrong_value("magic", TRICORDER_EEPROM_MAGIC,
94 be32_to_cpu(eeprom->magic));
95 return 1;
96 }
97
98 switch (be16_to_cpu(eeprom->version)) {
99 case 0:
100 return handle_eeprom_v0(eeprom);
101 case 1:
102 return handle_eeprom_v1(eeprom);
103 default:
104 warn_wrong_value("version", TRICORDER_EEPROM_VERSION,
105 be16_to_cpu(eeprom->version));
106 return 1;
107 }
108}
109
110#if !defined(CONFIG_SPL)
111int tricorder_eeprom_read(unsigned devaddr)
112{
113 struct tricorder_eeprom eeprom;
114 int ret = tricorder_get_eeprom(devaddr, &eeprom);
115
116 if (ret)
117 return ret;
118
119 printf("Board type: %.*s\n",
120 sizeof(eeprom.board_name), eeprom.board_name);
121 printf("Board version: %.*s\n",
122 sizeof(eeprom.board_version), eeprom.board_version);
123 printf("Board serial: %.*s\n",
124 sizeof(eeprom.board_serial), eeprom.board_serial);
125 printf("Board interface version: %.*s\n",
126 sizeof(eeprom.interface_version),
127 eeprom.interface_version);
128
129 return ret;
130}
131
132int tricorder_eeprom_write(unsigned devaddr, const char *name,
133 const char *version, const char *serial, const char *interface)
134{
135 struct tricorder_eeprom eeprom, eeprom_verify;
136 size_t length;
137 uint32_t crc;
138 int ret;
139 unsigned char *p;
140 int i;
141#ifdef CONFIG_SYS_EEPROM_BUS_NUM
142 unsigned int bus;
143#endif
144
145 memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
146 memset(eeprom_verify, 0, TRICORDER_EEPROM_SIZE);
147
148 eeprom.magic = cpu_to_be32(TRICORDER_EEPROM_MAGIC);
149 eeprom.length = cpu_to_be16(TRICORDER_EEPROM_SIZE);
150 eeprom.version = cpu_to_be16(TRICORDER_EEPROM_VERSION);
151
152 length = min(sizeof(eeprom.board_name), strlen(name));
153 strncpy(eeprom.board_name, name, length);
154
155 length = min(sizeof(eeprom.board_version), strlen(version));
156 strncpy(eeprom.board_version, version, length);
157
158 length = min(sizeof(eeprom.board_serial), strlen(serial));
159 strncpy(eeprom.board_serial, serial, length);
160
161 if (interface) {
162 length = min(sizeof(eeprom.interface_version),
163 strlen(interface));
164 strncpy(eeprom.interface_version, interface, length);
165 }
166
167 crc = crc32(0L, (unsigned char *)&eeprom, TRICORDER_EEPROM_CRC_SIZE);
168 eeprom.crc32 = cpu_to_be32(crc);
169
170#if defined(DEBUG)
171 puts("Tricorder EEPROM content:\n");
172 print_buffer(0, &eeprom, 1, sizeof(eeprom), 16);
173#endif
174
175#ifdef CONFIG_SYS_EEPROM_BUS_NUM
176 bus = i2c_get_bus_num();
177 i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
178#endif
179
180
181 for (i = 0, p = (unsigned char *)&eeprom;
182 i < sizeof(eeprom);
183 i += 32, p += 32) {
184 ret = i2c_write(devaddr, i, CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
185 p, min(sizeof(eeprom) - i, 32));
186 if (ret)
187 break;
188 udelay(5000);
189 }
190
191 ret = i2c_read(devaddr, 0, 2, (unsigned char *)&eeprom_verify,
192 TRICORDER_EEPROM_SIZE);
193
194 if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
195 printf("Tricorder: Could not verify EEPROM content!\n");
196 ret = 1;
197 }
198
199#ifdef CONFIG_SYS_EEPROM_BUS_NUM
200 i2c_set_bus_num(bus);
201#endif
202 return ret;
203}
204
205int do_tricorder_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
206{
207 if (argc == 3) {
208 ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
209 eeprom_init();
210 if (strcmp(argv[1], "read") == 0) {
211 int rcode;
212
213 rcode = tricorder_eeprom_read(dev_addr);
214
215 return rcode;
216 }
217 } else if (argc == 6 || argc == 7) {
218 ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
219 char *name = argv[3];
220 char *version = argv[4];
221 char *serial = argv[5];
222 char *interface = NULL;
223 eeprom_init();
224
225 if (argc == 7)
226 interface = argv[6];
227
228 if (strcmp(argv[1], "write") == 0) {
229 int rcode;
230
231 rcode = tricorder_eeprom_write(dev_addr, name, version,
232 serial, interface);
233
234 return rcode;
235 }
236 }
237
238 return CMD_RET_USAGE;
239}
240
241U_BOOT_CMD(
242 tricordereeprom, 7, 1, do_tricorder_eeprom,
243 "Tricorder EEPROM",
244 "read devaddr\n"
245 " - read Tricorder EEPROM at devaddr and print content\n"
246 "tricordereeprom write devaddr name version serial [interface]\n"
247 " - write Tricorder EEPROM at devaddr with 'name', 'version'"
248 "and 'serial'\n"
249 " optional add an HW interface parameter"
250);
251#endif
252