Merge branch 'master' of git://www.denx.de/git/u-boot-imx
[oweals/u-boot.git] / board / corscience / tricorder / tricorder-eeprom.c
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
11 #include "tricorder-eeprom.h"
12
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
19 static 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         /* Ok the content is correct, do the conversion */
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
59 static 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
78 int tricorder_get_eeprom(int addr, struct tricorder_eeprom *eeprom)
79 {
80         unsigned int bus = i2c_get_bus_num();
81         i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
82
83         memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
84
85         i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
86         i2c_set_bus_num(bus);
87
88         if (be32_to_cpu(eeprom->magic) != TRICORDER_EEPROM_MAGIC) {
89                 warn_wrong_value("magic", TRICORDER_EEPROM_MAGIC,
90                                  be32_to_cpu(eeprom->magic));
91                 return 1;
92         }
93
94         switch (be16_to_cpu(eeprom->version)) {
95         case 0:
96                 return handle_eeprom_v0(eeprom);
97         case 1:
98                 return handle_eeprom_v1(eeprom);
99         default:
100                 warn_wrong_value("version", TRICORDER_EEPROM_VERSION,
101                                  be16_to_cpu(eeprom->version));
102                 return 1;
103         }
104 }
105
106 #if !defined(CONFIG_SPL)
107 int tricorder_eeprom_read(unsigned devaddr)
108 {
109         struct tricorder_eeprom eeprom;
110         int ret = tricorder_get_eeprom(devaddr, &eeprom);
111
112         if (ret)
113                 return ret;
114
115         printf("Board type:               %.*s\n",
116                sizeof(eeprom.board_name), eeprom.board_name);
117         printf("Board version:            %.*s\n",
118                sizeof(eeprom.board_version), eeprom.board_version);
119         printf("Board serial:             %.*s\n",
120                sizeof(eeprom.board_serial), eeprom.board_serial);
121         printf("Board interface version:  %.*s\n",
122                sizeof(eeprom.interface_version),
123                eeprom.interface_version);
124
125         return ret;
126 }
127
128 int tricorder_eeprom_write(unsigned devaddr, const char *name,
129                 const char *version, const char *serial, const char *interface)
130 {
131         struct tricorder_eeprom eeprom, eeprom_verify;
132         size_t length;
133         uint32_t crc;
134         int ret;
135         unsigned char *p;
136         int i;
137
138         memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
139         memset(eeprom_verify, 0, TRICORDER_EEPROM_SIZE);
140
141         eeprom.magic = cpu_to_be32(TRICORDER_EEPROM_MAGIC);
142         eeprom.length = cpu_to_be16(TRICORDER_EEPROM_SIZE);
143         eeprom.version = cpu_to_be16(TRICORDER_EEPROM_VERSION);
144
145         length = min(sizeof(eeprom.board_name), strlen(name));
146         strncpy(eeprom.board_name, name, length);
147
148         length = min(sizeof(eeprom.board_version), strlen(version));
149         strncpy(eeprom.board_version, version, length);
150
151         length = min(sizeof(eeprom.board_serial), strlen(serial));
152         strncpy(eeprom.board_serial, serial, length);
153
154         if (interface) {
155                 length = min(sizeof(eeprom.interface_version),
156                                 strlen(interface));
157                 strncpy(eeprom.interface_version, interface, length);
158         }
159
160         crc = crc32(0L, (unsigned char *)&eeprom, TRICORDER_EEPROM_CRC_SIZE);
161         eeprom.crc32 = cpu_to_be32(crc);
162
163 #if defined(DEBUG)
164         puts("Tricorder EEPROM content:\n");
165         print_buffer(0, &eeprom, 1, sizeof(eeprom), 16);
166 #endif
167
168         eeprom_init(CONFIG_SYS_EEPROM_BUS_NUM);
169
170         ret = eeprom_write(devaddr, 0, (unsigned char *)&eeprom,
171                         TRICORDER_EEPROM_SIZE);
172         if (ret)
173                 printf("Tricorder: Could not write EEPROM content!\n");
174
175         ret = eeprom_read(devaddr, 0, (unsigned char *)&eeprom_verify,
176                         TRICORDER_EEPROM_SIZE);
177         if (ret)
178                 printf("Tricorder: Could not read EEPROM content!\n");
179
180         if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
181                 printf("Tricorder: Could not verify EEPROM content!\n");
182                 ret = 1;
183         }
184
185         return ret;
186 }
187
188 int do_tricorder_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
189 {
190         if (argc == 3) {
191                 ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
192
193                 if (strcmp(argv[1], "read") == 0) {
194                         int rcode;
195
196                         rcode = tricorder_eeprom_read(dev_addr);
197
198                         return rcode;
199                 }
200         } else if (argc == 6 || argc == 7) {
201                 ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
202                 char *name = argv[3];
203                 char *version = argv[4];
204                 char *serial = argv[5];
205                 char *interface = NULL;
206
207                 if (argc == 7)
208                         interface = argv[6];
209
210                 if (strcmp(argv[1], "write") == 0) {
211                         int rcode;
212
213                         rcode = tricorder_eeprom_write(dev_addr, name, version,
214                                         serial, interface);
215
216                         return rcode;
217                 }
218         }
219
220         return CMD_RET_USAGE;
221 }
222
223 U_BOOT_CMD(
224         tricordereeprom,        7,      1,      do_tricorder_eeprom,
225         "Tricorder EEPROM",
226         "read  devaddr\n"
227         "       - read Tricorder EEPROM at devaddr and print content\n"
228         "tricordereeprom write devaddr name version serial [interface]\n"
229         "       - write Tricorder EEPROM at devaddr with 'name', 'version'"
230         "and 'serial'\n"
231         "         optional add an HW interface parameter"
232 );
233 #endif /* CONFIG_SPL */