]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/w7o/vpd.c
SPDX: fix IBM-pibs license identifier
[people/ms/u-boot.git] / board / w7o / vpd.c
1 /*
2 * (C) Copyright 2001
3 * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8 #if defined(VXWORKS)
9 #include <stdio.h>
10 #include <string.h>
11 #define CONFIG_SYS_DEF_EEPROM_ADDR 0xa0
12 extern char iicReadByte(char, char);
13 extern ulong_t crc32(unsigned char *, unsigned long);
14 #else
15 #include <common.h>
16 #endif
17
18 #include "vpd.h"
19
20 /*
21 * vpd_reader() - reads VPD data from I2C EEPROMS.
22 * returns pointer to buffer or NULL.
23 */
24 static unsigned char *vpd_reader(unsigned char *buf, unsigned dev_addr,
25 unsigned off, unsigned count)
26 {
27 unsigned offset = off; /* Calculated offset */
28
29 /*
30 * The main board EEPROM contains
31 * SDRAM SPD in the first 128 bytes,
32 * so skew the offset.
33 */
34 if (dev_addr == CONFIG_SYS_DEF_EEPROM_ADDR)
35 offset += SDRAM_SPD_DATA_SIZE;
36
37 /* Try to read the I2C EEPROM */
38 #if defined(VXWORKS)
39 {
40 int i;
41
42 for (i = 0; i < count; ++i)
43 buf[i] = iicReadByte(dev_addr, offset + i);
44 }
45 #else
46 if (eeprom_read(dev_addr, offset, buf, count)) {
47 printf("Failed to read %d bytes from VPD EEPROM 0x%x @ 0x%x\n",
48 count, dev_addr, offset);
49 return NULL;
50 }
51 #endif
52
53 return buf;
54 }
55
56
57 /*
58 * vpd_get_packet() - returns next VPD packet or NULL.
59 */
60 static vpd_packet_t *vpd_get_packet(vpd_packet_t * vpd_packet)
61 {
62 vpd_packet_t *packet = vpd_packet;
63
64 if (packet != NULL) {
65 if (packet->identifier == VPD_PID_TERM)
66 return NULL;
67 else
68 packet = (vpd_packet_t *) ((char *) packet +
69 packet->size + 2);
70 }
71
72 return packet;
73 }
74
75
76 /*
77 * vpd_find_packet() - Locates and returns the specified
78 * VPD packet or NULL on error.
79 */
80 static vpd_packet_t *vpd_find_packet(vpd_t * vpd, unsigned char ident)
81 {
82 vpd_packet_t *packet = (vpd_packet_t *) &vpd->packets;
83
84 /* Guaranteed illegal */
85 if (ident == VPD_PID_GI)
86 return NULL;
87
88 /* Scan tuples looking for a match */
89 while ((packet->identifier != ident) &&
90 (packet->identifier != VPD_PID_TERM))
91 packet = vpd_get_packet(packet);
92
93 /* Did we find it? */
94 if ((packet->identifier) && (packet->identifier != ident))
95 return NULL;
96 return packet;
97 }
98
99
100 /*
101 * vpd_is_valid() - Validates contents of VPD data
102 * in I2C EEPROM. Returns 1 for
103 * success or 0 for failure.
104 */
105 static int vpd_is_valid(unsigned dev_addr, unsigned char *buf)
106 {
107 unsigned num_bytes;
108 vpd_packet_t *packet;
109 vpd_t *vpd = (vpd_t *) buf;
110 unsigned short stored_crc16, calc_crc16 = 0xffff;
111
112 /* Check Eyecatcher */
113 if (strncmp
114 ((char *) (vpd->header.eyecatcher), VPD_EYECATCHER,
115 VPD_EYE_SIZE) != 0) {
116 unsigned offset = 0;
117
118 if (dev_addr == CONFIG_SYS_DEF_EEPROM_ADDR)
119 offset += SDRAM_SPD_DATA_SIZE;
120 printf("Error: VPD EEPROM 0x%x corrupt @ 0x%x\n", dev_addr,
121 offset);
122
123 return 0;
124 }
125
126 /* Check Length */
127 if (vpd->header.size > VPD_MAX_EEPROM_SIZE) {
128 printf("Error: VPD EEPROM 0x%x contains bad size 0x%x\n",
129 dev_addr, vpd->header.size);
130 return 0;
131 }
132
133 /* Now find the termination packet */
134 packet = vpd_find_packet(vpd, VPD_PID_TERM);
135 if (packet == NULL) {
136 printf("Error: VPD EEPROM 0x%x missing termination packet\n",
137 dev_addr);
138 return 0;
139 }
140
141 /* Calculate data size */
142 num_bytes = (unsigned long) ((unsigned char *) packet -
143 (unsigned char *) vpd +
144 sizeof(vpd_packet_t));
145
146 /* Find stored CRC and clear it */
147 packet = vpd_find_packet(vpd, VPD_PID_CRC);
148 if (packet == NULL) {
149 printf("Error: VPD EEPROM 0x%x missing CRC\n", dev_addr);
150 return 0;
151 }
152 memcpy(&stored_crc16, packet->data, sizeof(ushort));
153 memset(packet->data, 0, sizeof(ushort));
154
155 /* OK, lets calculate the CRC and check it */
156 #if defined(VXWORKS)
157 calc_crc16 = (0xffff & crc32(buf, num_bytes));
158 #else
159 calc_crc16 = (0xffff & crc32(0, buf, num_bytes));
160 #endif
161 /* Now restore the CRC */
162 memcpy(packet->data, &stored_crc16, sizeof(ushort));
163 if (stored_crc16 != calc_crc16) {
164 printf("Error: VPD EEPROM 0x%x has bad CRC 0x%x\n",
165 dev_addr, stored_crc16);
166 return 0;
167 }
168
169 return 1;
170 }
171
172
173 /*
174 * size_ok() - Check to see if packet size matches
175 * size of data we want. Returns 1 for
176 * good match or 0 for failure.
177 */
178 static int size_ok(vpd_packet_t *packet, unsigned long size)
179 {
180 if (packet->size != size) {
181 printf("VPD Packet 0x%x corrupt.\n", packet->identifier);
182 return 0;
183 }
184 return 1;
185 }
186
187
188 /*
189 * strlen_ok() - Check to see if packet size matches
190 * strlen of the string we want to populate.
191 * Returns 1 for valid length or 0 for failure.
192 */
193 static int strlen_ok(vpd_packet_t *packet, unsigned long length)
194 {
195 if (packet->size >= length) {
196 printf("VPD Packet 0x%x corrupt.\n", packet->identifier);
197 return 0;
198 }
199 return 1;
200 }
201
202
203 /*
204 * get_vpd_data() - populates the passed VPD structure 'vpdInfo'
205 * with data obtained from the specified
206 * I2C EEPROM 'dev_addr'. Returns 0 for
207 * success or 1 for failure.
208 */
209 int vpd_get_data(unsigned char dev_addr, VPD *vpdInfo)
210 {
211 unsigned char buf[VPD_EEPROM_SIZE];
212 vpd_t *vpd = (vpd_t *) buf;
213 vpd_packet_t *packet;
214
215 if (vpdInfo == NULL)
216 return 1;
217
218 /*
219 * Fill vpdInfo with 0s to blank out
220 * unused fields, fill vpdInfo->ethAddrs
221 * with all 0xffs so that other's code can
222 * determine how many real Ethernet addresses
223 * there are. OUIs starting with 0xff are
224 * broadcast addresses, and would never be
225 * permantely stored.
226 */
227 memset((void *) vpdInfo, 0, sizeof(VPD));
228 memset((void *) &vpdInfo->ethAddrs, 0xff, sizeof(vpdInfo->ethAddrs));
229 vpdInfo->_devAddr = dev_addr;
230
231 /* Read the minimum size first */
232 if (vpd_reader(buf, dev_addr, 0, VPD_EEPROM_SIZE) == NULL)
233 return 1;
234
235 /* Check validity of VPD data */
236 if (!vpd_is_valid(dev_addr, buf)) {
237 printf("VPD Data is INVALID!\n");
238 return 1;
239 }
240
241 /*
242 * Walk all the packets and populate
243 * the VPD info structure.
244 */
245 packet = (vpd_packet_t *) &vpd->packets;
246 do {
247 switch (packet->identifier) {
248 case VPD_PID_GI:
249 printf("Error: Illegal VPD value\n");
250 break;
251 case VPD_PID_PID:
252 if (strlen_ok(packet, MAX_PROD_ID)) {
253 strncpy(vpdInfo->productId,
254 (char *) (packet->data),
255 packet->size);
256 }
257 break;
258 case VPD_PID_REV:
259 if (size_ok(packet, sizeof(char)))
260 vpdInfo->revisionId = *packet->data;
261 break;
262 case VPD_PID_SN:
263 if (size_ok(packet, sizeof(unsigned long))) {
264 memcpy(&vpdInfo->serialNum,
265 packet->data,
266 sizeof(unsigned long));
267 }
268 break;
269 case VPD_PID_MANID:
270 if (size_ok(packet, sizeof(unsigned char)))
271 vpdInfo->manuID = *packet->data;
272 break;
273 case VPD_PID_PCO:
274 if (size_ok(packet, sizeof(unsigned long))) {
275 memcpy(&vpdInfo->configOpt,
276 packet->data,
277 sizeof(unsigned long));
278 }
279 break;
280 case VPD_PID_SYSCLK:
281 if (size_ok(packet, sizeof(unsigned long)))
282 memcpy(&vpdInfo->sysClk,
283 packet->data,
284 sizeof(unsigned long));
285 break;
286 case VPD_PID_SERCLK:
287 if (size_ok(packet, sizeof(unsigned long)))
288 memcpy(&vpdInfo->serClk,
289 packet->data,
290 sizeof(unsigned long));
291 break;
292 case VPD_PID_FLASH:
293 if (size_ok(packet, 9)) { /* XXX - hardcoded,
294 padding in struct */
295 memcpy(&vpdInfo->flashCfg, packet->data, 9);
296 }
297 break;
298 case VPD_PID_ETHADDR:
299 memcpy(vpdInfo->ethAddrs, packet->data, packet->size);
300 break;
301 case VPD_PID_POTS:
302 if (size_ok(packet, sizeof(char)))
303 vpdInfo->numPOTS = (unsigned) *packet->data;
304 break;
305 case VPD_PID_DS1:
306 if (size_ok(packet, sizeof(char)))
307 vpdInfo->numDS1 = (unsigned) *packet->data;
308 case VPD_PID_GAL:
309 case VPD_PID_CRC:
310 case VPD_PID_TERM:
311 break;
312 default:
313 printf("Warning: Found unknown VPD packet ID 0x%x\n",
314 packet->identifier);
315 break;
316 }
317 } while ((packet = vpd_get_packet(packet)));
318
319 return 0;
320 }
321
322
323 /*
324 * vpd_init() - Initialize default VPD environment
325 */
326 int vpd_init(unsigned char dev_addr)
327 {
328 return 0;
329 }
330
331
332 /*
333 * vpd_print() - Pretty print the VPD data.
334 */
335 void vpd_print(VPD *vpdInfo)
336 {
337 const char *const sp = "";
338 const char *const sfmt = "%4s%-20s: \"%s\"\n";
339 const char *const cfmt = "%4s%-20s: '%c'\n";
340 const char *const dfmt = "%4s%-20s: %ld\n";
341 const char *const hfmt = "%4s%-20s: %08lX\n";
342 const char *const dsfmt = "%4s%-20s: %d\n";
343 const char *const hsfmt = "%4s%-20s: %04X\n";
344 const char *const dhfmt = "%4s%-20s: %ld (%lX)\n";
345
346 printf("VPD read from I2C device: %02X\n", vpdInfo->_devAddr);
347
348 if (vpdInfo->productId[0])
349 printf(sfmt, sp, "Product ID", vpdInfo->productId);
350 else
351 printf(sfmt, sp, "Product ID", "UNKNOWN");
352
353 if (vpdInfo->revisionId)
354 printf(cfmt, sp, "Revision ID", vpdInfo->revisionId);
355
356 if (vpdInfo->serialNum)
357 printf(dfmt, sp, "Serial Number", vpdInfo->serialNum);
358
359 if (vpdInfo->manuID)
360 printf(dfmt, sp, "Manufacture ID", (long) vpdInfo->manuID);
361
362 if (vpdInfo->configOpt)
363 printf(hfmt, sp, "Configuration", vpdInfo->configOpt);
364
365 if (vpdInfo->sysClk)
366 printf(dhfmt, sp, "System Clock", vpdInfo->sysClk,
367 vpdInfo->sysClk);
368
369 if (vpdInfo->serClk)
370 printf(dhfmt, sp, "Serial Clock", vpdInfo->serClk,
371 vpdInfo->serClk);
372
373 if (vpdInfo->numPOTS)
374 printf(dfmt, sp, "Number of POTS lines", vpdInfo->numPOTS);
375
376 if (vpdInfo->numDS1)
377 printf(dfmt, sp, "Number of DS1s", vpdInfo->numDS1);
378
379 /* Print Ethernet Addresses */
380 if (vpdInfo->ethAddrs[0][0] != 0xff) {
381 int i, j;
382
383 printf("%4sEtherNet Address(es): ", sp);
384 for (i = 0; i < MAX_ETH_ADDRS; i++) {
385 if (vpdInfo->ethAddrs[i][0] != 0xff) {
386 for (j = 0; j < 6; j++) {
387 printf("%02X",
388 vpdInfo->ethAddrs[i][j]);
389 if (((j + 1) % 6) != 0)
390 printf(":");
391 else
392 printf(" ");
393 }
394 if (((i + 1) % 3) == 0)
395 printf("\n%24s: ", sp);
396 }
397 }
398 printf("\n");
399 }
400
401 if (vpdInfo->flashCfg.mfg && vpdInfo->flashCfg.dev) {
402 printf("Main Flash Configuration:\n");
403 printf(hsfmt, sp, "Manufacture ID", vpdInfo->flashCfg.mfg);
404 printf(hsfmt, sp, "Device ID", vpdInfo->flashCfg.dev);
405 printf(dsfmt, sp, "Device Width", vpdInfo->flashCfg.devWidth);
406 printf(dsfmt, sp, "Num. Devices", vpdInfo->flashCfg.numDevs);
407 printf(dsfmt, sp, "Num. Columns", vpdInfo->flashCfg.numCols);
408 printf(dsfmt, sp, "Column Width", vpdInfo->flashCfg.colWidth);
409 printf(dsfmt, sp, "WE Data Width",
410 vpdInfo->flashCfg.weDataWidth);
411 }
412 }