]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/hymod/eeprom.c
Initial revision
[karo-tx-uboot.git] / board / hymod / eeprom.c
1 /*
2  * (C) Copyright 2001
3  * Murray Jensen, CSIRO Manufacturing Science and Technology,
4  * <Murray.Jensen@cmst.csiro.au>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 #include <common.h>
26 #include <mpc8260.h>
27
28 /* imports from fetch.c */
29 extern int fetch_and_parse(bd_t *, char *, ulong, int (*)(uchar *, uchar *));
30
31 int
32 eeprom_load(unsigned offset, hymod_eeprom_t *ep)
33 {
34     uchar data[HYMOD_EEPROM_SIZE], *dp, *edp;
35     hymod_eehdr_t *hp;
36     ulong len, crc;
37
38     memset(ep, 0, sizeof *ep);
39     memset(data, 0, HYMOD_EEPROM_SIZE);
40     crc = 0;
41
42     hp = (hymod_eehdr_t *)data;
43     eeprom_read(CFG_DEF_EEPROM_ADDR, offset, (uchar *)hp, sizeof (*hp));
44     offset += sizeof (*hp);
45
46     if (hp->id != HYMOD_EEPROM_ID || hp->ver > HYMOD_EEPROM_VER ||
47       (len = hp->len) > HYMOD_EEPROM_MAXLEN)
48         return (0);
49
50     dp = (uchar *)(hp + 1); edp = dp + len;
51     eeprom_read(CFG_DEF_EEPROM_ADDR, offset, dp, len);
52     offset += len;
53
54     eeprom_read(CFG_DEF_EEPROM_ADDR, offset, (uchar *)&crc, sizeof (ulong));
55
56     if (crc32(0, data, edp - data) != crc)
57         return (0);
58
59     ep->ver = hp->ver;
60
61     for (;;) {
62         hymod_eerec_t *rp = (hymod_eerec_t *)dp;
63         ulong rtyp;
64         uchar rlen, *rdat;
65         uint rsiz;
66
67         if (rp->small.topbit == 0) {
68             rtyp = rp->small.type;
69             rlen = rp->small.len;
70             rdat = rp->small.data;
71             rsiz = offsetof(hymod_eerec_t, small.data) + rlen;
72         }
73         else if (rp->medium.nxtbit == 0) {
74             rtyp = rp->medium.type;
75             rlen = rp->medium.len;
76             rdat = rp->medium.data;
77             rsiz = offsetof(hymod_eerec_t, medium.data) + rlen;
78         }
79         else {
80             rtyp = rp->large.type;
81             rlen = rp->large.len;
82             rdat = rp->large.data;
83             rsiz = offsetof(hymod_eerec_t, large.data) + rlen;
84         }
85
86         if (rtyp == 0)
87             break;
88
89         dp += rsiz;
90         if (dp > edp)   /* error? */
91             break;
92
93         switch (rtyp) {
94
95         case HYMOD_EEREC_SERNO:         /* serial number */
96             if (rlen == sizeof (ulong))
97                 memcpy(&ep->serno, rdat, sizeof (ulong));
98             break;
99
100         case HYMOD_EEREC_DATE:          /* date */
101             if (rlen == sizeof (hymod_date_t))
102                 memcpy(&ep->date, rdat, sizeof (hymod_date_t));
103             break;
104
105         case HYMOD_EEREC_BATCH:         /* batch */
106             if (rlen <= HYMOD_MAX_BATCH)
107                 memcpy(ep->batch, rdat, ep->batchlen = rlen);
108             break;
109
110         case HYMOD_EEREC_TYPE:          /* board type */
111             if (rlen == 1)
112                 ep->bdtype = *rdat;
113             break;
114
115         case HYMOD_EEREC_REV:           /* board revision */
116             if (rlen == 1)
117                 ep->bdrev = *rdat;
118             break;
119
120         case HYMOD_EEREC_SDRAM:         /* sdram size(s) */
121             if (rlen > 0 && rlen <= HYMOD_MAX_SDRAM) {
122                 int i;
123
124                 for (i = 0; i < rlen; i++)
125                     ep->sdramsz[i] = rdat[i];
126                 ep->nsdram = rlen;
127             }
128             break;
129
130         case HYMOD_EEREC_FLASH:         /* flash size(s) */
131             if (rlen > 0 && rlen <= HYMOD_MAX_FLASH) {
132                 int i;
133
134                 for (i = 0; i < rlen; i++)
135                     ep->flashsz[i] = rdat[i];
136                 ep->nflash = rlen;
137             }
138             break;
139
140         case HYMOD_EEREC_ZBT:           /* zbt ram size(s) */
141             if (rlen > 0 && rlen <= HYMOD_MAX_ZBT) {
142                 int i;
143
144                 for (i = 0; i < rlen; i++)
145                     ep->zbtsz[i] = rdat[i];
146                 ep->nzbt = rlen;
147             }
148             break;
149
150         case HYMOD_EEREC_XLXTYP:        /* xilinx fpga type(s) */
151             if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
152                 int i;
153
154                 for (i = 0; i < rlen; i++)
155                     ep->xlx[i].type = rdat[i];
156                 ep->nxlx = rlen;
157             }
158             break;
159
160         case HYMOD_EEREC_XLXSPD:        /* xilinx fpga speed(s) */
161             if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
162                 int i;
163
164                 for (i = 0; i < rlen; i++)
165                     ep->xlx[i].speed = rdat[i];
166             }
167             break;
168
169         case HYMOD_EEREC_XLXTMP:        /* xilinx fpga temperature(s) */
170             if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
171                 int i;
172
173                 for (i = 0; i < rlen; i++)
174                     ep->xlx[i].temp = rdat[i];
175             }
176             break;
177
178         case HYMOD_EEREC_XLXGRD:        /* xilinx fpga grade(s) */
179             if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
180                 int i;
181
182                 for (i = 0; i < rlen; i++)
183                     ep->xlx[i].grade = rdat[i];
184             }
185             break;
186
187         case HYMOD_EEREC_CPUTYP:        /* CPU type */
188             if (rlen == 1)
189                 ep->mpc.type = *rdat;
190             break;
191
192         case HYMOD_EEREC_CPUSPD:        /* CPU speed */
193             if (rlen == 1)
194                 ep->mpc.cpuspd = *rdat;
195             break;
196
197         case HYMOD_EEREC_CPMSPD:        /* CPM speed */
198             if (rlen == 1)
199                 ep->mpc.cpmspd = *rdat;
200             break;
201
202         case HYMOD_EEREC_BUSSPD:        /* bus speed */
203             if (rlen == 1)
204                 ep->mpc.busspd = *rdat;
205             break;
206
207         case HYMOD_EEREC_HSTYPE:        /* high-speed serial chip type */
208             if (rlen == 1)
209                 ep->hss.type = *rdat;
210             break;
211
212         case HYMOD_EEREC_HSCHIN:        /* high-speed serial input channels */
213             if (rlen == 1)
214                 ep->hss.nchin = *rdat;
215             break;
216
217         case HYMOD_EEREC_HSCHOUT:       /* high-speed serial output channels */
218             if (rlen == 1)
219                 ep->hss.nchout = *rdat;
220             break;
221
222         default:        /* ignore */
223             break;
224         }
225     }
226
227     return (1);
228 }
229
230 /* maps an ascii "name=value" into a binary eeprom data record */
231 typedef
232     struct _eerec_map {
233         char *name;
234         uint type;
235         uchar *(*handler)(struct _eerec_map *, uchar *, uchar *, uchar *);
236         uint length;
237         uint maxlen;
238     }
239 eerec_map_t;
240
241 static uchar *
242 uint_handler(eerec_map_t *rp, uchar *value, uchar *dp, uchar *edp)
243 {
244     uchar *eval;
245     union {
246         uchar cval[4];
247         ushort sval[2];
248         ulong lval;
249     } rdata;
250
251     rdata.lval = simple_strtol(value, (char **)&eval, 10);
252
253     if (eval == value || *eval != '\0') {
254         printf("%s record (%s) is not a valid uint\n", rp->name, value);
255         return (NULL);
256     }
257
258     if (dp + 2 + rp->length > edp) {
259         printf("can't fit %s record into eeprom\n", rp->name);
260         return (NULL);
261     }
262
263     *dp++ = rp->type;
264     *dp++ = rp->length;
265
266     switch (rp->length) {
267
268     case 1:
269         if (rdata.lval >= 256) {
270             printf("%s record value (%lu) out of range (0-255)\n",
271                 rp->name, rdata.lval);
272             return (NULL);
273         }
274         *dp++ = rdata.cval[3];
275         break;
276
277     case 2:
278         if (rdata.lval >= 65536) {
279             printf("%s record value (%lu) out of range (0-65535)\n",
280                 rp->name, rdata.lval);
281             return (NULL);
282         }
283         memcpy(dp, &rdata.sval[1], 2);
284         dp += 2;
285         break;
286
287     case 4:
288         memcpy(dp, &rdata.lval, 4);
289         dp += 4;
290         break;
291
292     default:
293         printf("huh? rp->length not 1, 2 or 4! (%d)\n", rp->length);
294         return (NULL);
295     }
296
297     return (dp);
298 }
299
300 static uchar *
301 date_handler(eerec_map_t *rp, uchar *value, uchar *dp, uchar *edp)
302 {
303     hymod_date_t date;
304     uchar *p = value, *ep;
305
306     date.year = simple_strtol(p, (char **)&ep, 10);
307     if (ep == p || *ep++ != '-') {
308 bad_date:
309         printf("%s record (%s) is not a valid date\n", rp->name, value);
310         return (NULL);
311     }
312
313     date.month = simple_strtol(p = ep, (char **)&ep, 10);
314     if (ep == p || *ep++ != '-' || date.month == 0 || date.month > 12)
315         goto bad_date;
316
317     date.day = simple_strtol(p = ep, (char **)&ep, 10);
318     if (ep == p || *ep != '\0' || date.day == 0 || date.day > 31)
319         goto bad_date;
320
321     if (dp + 2 + sizeof (hymod_date_t) > edp) {
322         printf("can't fit %s record into eeprom\n", rp->name);
323         return (NULL);
324     }
325
326     *dp++ = rp->type;
327     *dp++ = sizeof (hymod_date_t);
328     memcpy(dp, &date, sizeof (hymod_date_t));
329     dp += sizeof (hymod_date_t);
330
331     return (dp);
332 }
333
334 static uchar *
335 string_handler(eerec_map_t *rp, uchar *value, uchar *dp, uchar *edp)
336 {
337     uint len;
338
339     if ((len = strlen(value)) > rp->maxlen) {
340         printf("%s record (%s) string is too long (%d>%d)\n",
341             rp->name, value, len, rp->maxlen);
342         return (NULL);
343     }
344
345     if (dp + 2 + len > edp) {
346         printf("can't fit %s record into eeprom\n", rp->name);
347         return (NULL);
348     }
349
350     *dp++ = rp->type;
351     *dp++ = len;
352     memcpy(dp, value, len);
353     dp += len;
354
355     return (dp);
356 }
357
358 static uchar *
359 bytes_handler(eerec_map_t *rp, uchar *value, uchar *dp, uchar *edp)
360 {
361     uchar bytes[HYMOD_MAX_BYTES], nbytes = 0;
362     uchar *p = value, *ep;
363
364     for (;;) {
365
366         if (nbytes >= HYMOD_MAX_BYTES) {
367             printf("%s record (%s) byte array too long\n", rp->name, value);
368             return (NULL);
369         }
370
371         bytes[nbytes++] = simple_strtol(p, (char **)&ep, 10);
372
373         if (ep == p || (*ep != '\0' && *ep != ',')) {
374             printf("%s record (%s) byte array has invalid uint\n",
375                 rp->name, value);
376             return (NULL);
377         }
378
379         if (*ep++ == '\0')
380             break;
381
382         p = ep;
383     }
384
385     if (dp + 2 + nbytes > edp) {
386         printf("can't fit %s record into eeprom\n", rp->name);
387         return (NULL);
388     }
389
390     *dp++ = rp->type;
391     *dp++ = nbytes;
392     memcpy(dp, bytes, nbytes);
393     dp += nbytes;
394
395     return (dp);
396 }
397
398 static eerec_map_t eerec_map[] = {
399    /* name       type                 handler         len max             */
400     { "serno",   HYMOD_EEREC_SERNO,   uint_handler,   4,  0               },
401     { "date",    HYMOD_EEREC_DATE,    date_handler,   4,  0               },
402     { "batch",   HYMOD_EEREC_BATCH,   string_handler, 0,  HYMOD_MAX_BATCH },
403     { "type",    HYMOD_EEREC_TYPE,    uint_handler,   1,  0               },
404     { "rev",     HYMOD_EEREC_REV,     uint_handler,   1,  0               },
405     { "sdram",   HYMOD_EEREC_SDRAM,   bytes_handler,  0,  HYMOD_MAX_SDRAM },
406     { "flash",   HYMOD_EEREC_FLASH,   bytes_handler,  0,  HYMOD_MAX_FLASH },
407     { "zbt",     HYMOD_EEREC_ZBT,     bytes_handler,  0,  HYMOD_MAX_ZBT   },
408     { "xlxtyp",  HYMOD_EEREC_XLXTYP,  bytes_handler,  0,  HYMOD_MAX_XLX   },
409     { "xlxspd",  HYMOD_EEREC_XLXSPD,  bytes_handler,  0,  HYMOD_MAX_XLX   },
410     { "xlxtmp",  HYMOD_EEREC_XLXTMP,  bytes_handler,  0,  HYMOD_MAX_XLX   },
411     { "xlxgrd",  HYMOD_EEREC_XLXGRD,  bytes_handler,  0,  HYMOD_MAX_XLX   },
412     { "cputyp",  HYMOD_EEREC_CPUTYP,  uint_handler,   1,  0               },
413     { "cpuspd",  HYMOD_EEREC_CPUSPD,  uint_handler,   1,  0               },
414     { "cpmspd",  HYMOD_EEREC_CPMSPD,  uint_handler,   1,  0               },
415     { "busspd",  HYMOD_EEREC_BUSSPD,  uint_handler,   1,  0               },
416     { "hstype",  HYMOD_EEREC_HSTYPE,  uint_handler,   1,  0               },
417     { "hschin",  HYMOD_EEREC_HSCHIN,  uint_handler,   1,  0               },
418     { "hschout", HYMOD_EEREC_HSCHOUT, uint_handler,   1,  0               },
419 };
420
421 static int neerecs = sizeof eerec_map / sizeof eerec_map[0];
422
423 static uchar data[HYMOD_EEPROM_SIZE], *sdp, *dp, *edp;
424
425 static int
426 eeprom_fetch_callback(uchar *name, uchar *value)
427 {
428     eerec_map_t *rp;
429
430     for (rp = eerec_map; rp < &eerec_map[neerecs]; rp++)
431         if (strcmp(name, rp->name) == 0)
432             break;
433
434     if (rp >= &eerec_map[neerecs])
435         return (0);
436
437     if ((dp = (*rp->handler)(rp, value, dp, edp)) == NULL)
438         return (0);
439
440     return (1);
441 }
442
443 int
444 eeprom_fetch(unsigned offset, bd_t *bd, char *filename, ulong addr)
445 {
446     hymod_eehdr_t *hp = (hymod_eehdr_t *)&data[0];
447     ulong crc;
448
449     hp->id = HYMOD_EEPROM_ID;
450     hp->ver = HYMOD_EEPROM_VER;
451
452     dp = sdp = (uchar *)(hp + 1);
453     edp = dp + HYMOD_EEPROM_MAXLEN;
454
455     if (fetch_and_parse(bd, filename, addr, eeprom_fetch_callback) == 0)
456         return (0);
457
458     hp->len = dp - sdp;
459
460     crc = crc32(0, data, dp - data);
461     memcpy(dp, &crc, sizeof (ulong));
462     dp += sizeof (ulong);
463
464     eeprom_write(CFG_DEF_EEPROM_ADDR, offset, data, dp - data);
465
466     return (1);
467 }
468
469 static char *type_vals[] = {
470     "NONE", "IO", "CLP", "DSP", "INPUT", "ALT-INPUT", "DISPLAY"
471 };
472
473 static char *xlxtyp_vals[] = {
474     "NONE", "XCV300E", "XCV400E", "XCV600E"
475 };
476
477 static char *xlxspd_vals[] = {
478     "NONE", "6", "7", "8"
479 };
480
481 static char *xlxtmp_vals[] = {
482     "NONE", "COM", "IND"
483 };
484
485 static char *xlxgrd_vals[] = {
486     "NONE", "NORMAL", "ENGSAMP"
487 };
488
489 static char *cputyp_vals[] = {
490     "NONE", "MPC8260"
491 };
492
493 static char *clk_vals[] = {
494     "NONE", "33", "66", "100", "133", "166", "200"
495 };
496
497 static char *hstype_vals[] = {
498     "NONE", "AMCC-S2064A"
499 };
500
501 static void
502 print_mem(char *l, char *s, uchar n, uchar a[])
503 {
504     if (n > 0) {
505         if (n == 1)
506             printf("%s%dMB %s", s, 1 << (a[0] - 20), l);
507         else {
508             ulong t = 0;
509             int i;
510
511             for (i = 0; i < n; i++)
512                 t += 1 << (a[i] - 20);
513
514             printf("%s%luMB %s (%d banks:", s, t, l, n);
515
516             for (i = 0; i < n; i++)
517                 printf("%dMB%s", 1 << (a[i] - 20), (i == n - 1) ? ")" : ",");
518         }
519     }
520     else
521         printf("%sNO %s", s, l);
522 }
523
524 void
525 eeprom_print(hymod_eeprom_t *ep)
526 {
527     int i;
528
529     printf("         Hymod %s board, rev %03d\n",
530         type_vals[ep->bdtype], ep->bdrev);
531
532     printf("         serial #: %010lu, date %04d-%02d-%02d",
533         ep->serno, ep->date.year, ep->date.month, ep->date.day);
534     if (ep->batchlen > 0)
535         printf(", batch \"%.*s\"", ep->batchlen, ep->batch);
536     puts("\n");
537
538     switch (ep->bdtype) {
539
540     case HYMOD_BDTYPE_IO:
541     case HYMOD_BDTYPE_CLP:
542     case HYMOD_BDTYPE_DSP:
543         printf("         Motorola %s CPU, speeds: %s/%s/%s",
544             cputyp_vals[ep->mpc.type], clk_vals[ep->mpc.cpuspd],
545             clk_vals[ep->mpc.cpmspd], clk_vals[ep->mpc.busspd]);
546
547         print_mem("SDRAM", ", ", ep->nsdram, ep->sdramsz);
548
549         print_mem("FLASH", ", ", ep->nflash, ep->flashsz);
550
551         puts("\n");
552
553         print_mem("ZBT", "         ", ep->nzbt, ep->zbtsz);
554
555         if (ep->nxlx > 0) {
556             hymod_xlx_t *xp;
557
558             if (ep->nxlx == 1) {
559                 xp = &ep->xlx[0];
560                 printf(", Xilinx %s FPGA (%s/%s/%s)",
561                     xlxtyp_vals[xp->type], xlxspd_vals[xp->speed],
562                     xlxtmp_vals[xp->temp], xlxgrd_vals[xp->grade]);
563             }
564             else {
565                 printf(", %d Xilinx FPGAs (", ep->nxlx);
566                 for (i = 0; i < ep->nxlx; i++) {
567                     xp = &ep->xlx[i];
568                     printf("%s[%s/%s/%s]%s",
569                         xlxtyp_vals[xp->type], xlxspd_vals[xp->speed],
570                         xlxtmp_vals[xp->temp], xlxgrd_vals[xp->grade],
571                         (i == ep->nxlx - 1) ? ")" : ", ");
572                 }
573             }
574         }
575         else
576             puts(", NO FPGAs");
577
578         puts("\n");
579
580         if (ep->hss.type > 0)
581             printf("         High Speed Serial: %s, %d input%s, %d output%s\n",
582                 hstype_vals[ep->hss.type],
583                 ep->hss.nchin, (ep->hss.nchin == 1 ? "" : "s"),
584                 ep->hss.nchout, (ep->hss.nchout == 1 ? "" : "s"));
585         break;
586
587     case HYMOD_BDTYPE_INPUT:
588     case HYMOD_BDTYPE_ALTINPUT:
589     case HYMOD_BDTYPE_DISPLAY:
590         break;
591
592     default:
593         /* crap! */
594         printf("         UNKNOWN BOARD TYPE: %d\n", ep->bdtype);
595         break;
596     }
597 }