blob: 4d48d7dbb083b3e73b29f3e6c141cdd2e5a6ea6d [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
2 * (C) Copyright 2001
wdenkb00ec162003-06-19 23:40:20 +00003 * Murray Jensen, CSIRO-MIT, <Murray.Jensen@csiro.au>
wdenkaffae2b2002-08-17 09:36:01 +00004 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <mpc8260.h>
26
27/* imports from fetch.c */
wdenkb00ec162003-06-19 23:40:20 +000028extern int fetch_and_parse (char *, ulong, int (*)(uchar *, uchar *));
wdenkaffae2b2002-08-17 09:36:01 +000029
wdenkb00ec162003-06-19 23:40:20 +000030/* imports from input.c */
31extern int hymod_get_serno (const char *);
32
33/* this is relative to the root of the server's tftp directory */
34static char *def_bddb_cfgdir = "/hymod/bddb";
35
36static int
37hymod_eeprom_load (int which, hymod_eeprom_t *ep)
wdenkaffae2b2002-08-17 09:36:01 +000038{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020039 unsigned dev_addr = CONFIG_SYS_I2C_EEPROM_ADDR | \
wdenkb00ec162003-06-19 23:40:20 +000040 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
41 unsigned offset = 0;
wdenkdbae5042003-06-21 00:17:24 +000042 uchar data[HYMOD_EEPROM_MAXLEN], *dp, *edp;
43 hymod_eehdr_t hdr;
wdenkb00ec162003-06-19 23:40:20 +000044 ulong len, crc;
wdenkaffae2b2002-08-17 09:36:01 +000045
wdenkb00ec162003-06-19 23:40:20 +000046 memset (ep, 0, sizeof *ep);
wdenkaffae2b2002-08-17 09:36:01 +000047
wdenkdbae5042003-06-21 00:17:24 +000048 eeprom_read (dev_addr, offset, (uchar *)&hdr, sizeof (hdr));
49 offset += sizeof (hdr);
wdenkaffae2b2002-08-17 09:36:01 +000050
wdenkdbae5042003-06-21 00:17:24 +000051 if (hdr.id != HYMOD_EEPROM_ID || hdr.ver > HYMOD_EEPROM_VER ||
52 (len = hdr.len) > HYMOD_EEPROM_MAXLEN)
wdenkb00ec162003-06-19 23:40:20 +000053 return (0);
wdenkaffae2b2002-08-17 09:36:01 +000054
wdenkdbae5042003-06-21 00:17:24 +000055 eeprom_read (dev_addr, offset, data, len);
wdenkb00ec162003-06-19 23:40:20 +000056 offset += len;
wdenkaffae2b2002-08-17 09:36:01 +000057
wdenkb00ec162003-06-19 23:40:20 +000058 eeprom_read (dev_addr, offset, (uchar *)&crc, sizeof (ulong));
wdenkdbae5042003-06-21 00:17:24 +000059 offset += sizeof (ulong);
wdenkaffae2b2002-08-17 09:36:01 +000060
Wolfgang Denk7fb52662005-10-13 16:45:02 +020061 if (crc32 (crc32 (0, (uchar *)&hdr, sizeof hdr), data, len) != crc)
wdenkb00ec162003-06-19 23:40:20 +000062 return (0);
wdenkaffae2b2002-08-17 09:36:01 +000063
wdenkdbae5042003-06-21 00:17:24 +000064 ep->ver = hdr.ver;
65 dp = data; edp = dp + len;
wdenkaffae2b2002-08-17 09:36:01 +000066
wdenkb00ec162003-06-19 23:40:20 +000067 for (;;) {
wdenkb00ec162003-06-19 23:40:20 +000068 ulong rtyp;
69 uchar rlen, *rdat;
wdenkaffae2b2002-08-17 09:36:01 +000070
wdenkdbae5042003-06-21 00:17:24 +000071 rtyp = *dp++;
72 if ((rtyp & 0x80) == 0)
73 rlen = *dp++;
wdenkb00ec162003-06-19 23:40:20 +000074 else {
wdenkdbae5042003-06-21 00:17:24 +000075 uchar islarge = rtyp & 0x40;
76
77 rtyp = ((rtyp & 0x3f) << 8) | *dp++;
78 if (islarge) {
79 rtyp = (rtyp << 8) | *dp++;
80 rtyp = (rtyp << 8) | *dp++;
81 }
82
83 rlen = *dp++;
84 rlen = (rlen << 8) | *dp++;
85 if (islarge) {
86 rlen = (rlen << 8) | *dp++;
87 rlen = (rlen << 8) | *dp++;
88 }
wdenkb00ec162003-06-19 23:40:20 +000089 }
wdenkaffae2b2002-08-17 09:36:01 +000090
wdenkb00ec162003-06-19 23:40:20 +000091 if (rtyp == 0)
92 break;
wdenkaffae2b2002-08-17 09:36:01 +000093
wdenkdbae5042003-06-21 00:17:24 +000094 rdat = dp;
95 dp += rlen;
96
wdenkb00ec162003-06-19 23:40:20 +000097 if (dp > edp) /* error? */
98 break;
wdenkaffae2b2002-08-17 09:36:01 +000099
wdenkb00ec162003-06-19 23:40:20 +0000100 switch (rtyp) {
wdenkaffae2b2002-08-17 09:36:01 +0000101
wdenkb00ec162003-06-19 23:40:20 +0000102 case HYMOD_EEREC_SERNO: /* serial number */
103 if (rlen == sizeof (ulong))
wdenkdbae5042003-06-21 00:17:24 +0000104 ep->serno = \
105 ((ulong)rdat[0] << 24) | \
106 ((ulong)rdat[1] << 16) | \
107 ((ulong)rdat[2] << 8) | \
108 (ulong)rdat[3];
wdenkb00ec162003-06-19 23:40:20 +0000109 break;
wdenkaffae2b2002-08-17 09:36:01 +0000110
wdenkb00ec162003-06-19 23:40:20 +0000111 case HYMOD_EEREC_DATE: /* date */
wdenkdbae5042003-06-21 00:17:24 +0000112 if (rlen == sizeof (hymod_date_t)) {
113 ep->date.year = ((ushort)rdat[0] << 8) | \
114 (ushort)rdat[1];
115 ep->date.month = rdat[2];
116 ep->date.day = rdat[3];
117 }
wdenkb00ec162003-06-19 23:40:20 +0000118 break;
wdenkaffae2b2002-08-17 09:36:01 +0000119
wdenkb00ec162003-06-19 23:40:20 +0000120 case HYMOD_EEREC_BATCH: /* batch */
121 if (rlen <= HYMOD_MAX_BATCH)
122 memcpy (ep->batch, rdat, ep->batchlen = rlen);
123 break;
wdenkaffae2b2002-08-17 09:36:01 +0000124
wdenkb00ec162003-06-19 23:40:20 +0000125 case HYMOD_EEREC_TYPE: /* board type */
126 if (rlen == 1)
127 ep->bdtype = *rdat;
128 break;
wdenkaffae2b2002-08-17 09:36:01 +0000129
wdenkb00ec162003-06-19 23:40:20 +0000130 case HYMOD_EEREC_REV: /* board revision */
131 if (rlen == 1)
132 ep->bdrev = *rdat;
133 break;
wdenkaffae2b2002-08-17 09:36:01 +0000134
wdenkb00ec162003-06-19 23:40:20 +0000135 case HYMOD_EEREC_SDRAM: /* sdram size(s) */
136 if (rlen > 0 && rlen <= HYMOD_MAX_SDRAM) {
137 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000138
wdenkb00ec162003-06-19 23:40:20 +0000139 for (i = 0; i < rlen; i++)
140 ep->sdramsz[i] = rdat[i];
141 ep->nsdram = rlen;
142 }
143 break;
wdenkaffae2b2002-08-17 09:36:01 +0000144
wdenkb00ec162003-06-19 23:40:20 +0000145 case HYMOD_EEREC_FLASH: /* flash size(s) */
146 if (rlen > 0 && rlen <= HYMOD_MAX_FLASH) {
147 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000148
wdenkb00ec162003-06-19 23:40:20 +0000149 for (i = 0; i < rlen; i++)
150 ep->flashsz[i] = rdat[i];
151 ep->nflash = rlen;
152 }
153 break;
wdenkaffae2b2002-08-17 09:36:01 +0000154
wdenkb00ec162003-06-19 23:40:20 +0000155 case HYMOD_EEREC_ZBT: /* zbt ram size(s) */
156 if (rlen > 0 && rlen <= HYMOD_MAX_ZBT) {
157 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000158
wdenkb00ec162003-06-19 23:40:20 +0000159 for (i = 0; i < rlen; i++)
160 ep->zbtsz[i] = rdat[i];
161 ep->nzbt = rlen;
162 }
163 break;
wdenkaffae2b2002-08-17 09:36:01 +0000164
wdenkb00ec162003-06-19 23:40:20 +0000165 case HYMOD_EEREC_XLXTYP: /* xilinx fpga type(s) */
166 if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
167 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000168
wdenkb00ec162003-06-19 23:40:20 +0000169 for (i = 0; i < rlen; i++)
170 ep->xlx[i].type = rdat[i];
171 ep->nxlx = rlen;
172 }
173 break;
wdenkaffae2b2002-08-17 09:36:01 +0000174
wdenkb00ec162003-06-19 23:40:20 +0000175 case HYMOD_EEREC_XLXSPD: /* xilinx fpga speed(s) */
176 if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
177 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000178
wdenkb00ec162003-06-19 23:40:20 +0000179 for (i = 0; i < rlen; i++)
180 ep->xlx[i].speed = rdat[i];
181 }
182 break;
wdenkaffae2b2002-08-17 09:36:01 +0000183
wdenkb00ec162003-06-19 23:40:20 +0000184 case HYMOD_EEREC_XLXTMP: /* xilinx fpga temperature(s) */
185 if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
186 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000187
wdenkb00ec162003-06-19 23:40:20 +0000188 for (i = 0; i < rlen; i++)
189 ep->xlx[i].temp = rdat[i];
190 }
191 break;
wdenkaffae2b2002-08-17 09:36:01 +0000192
wdenkb00ec162003-06-19 23:40:20 +0000193 case HYMOD_EEREC_XLXGRD: /* xilinx fpga grade(s) */
194 if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
195 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000196
wdenkb00ec162003-06-19 23:40:20 +0000197 for (i = 0; i < rlen; i++)
198 ep->xlx[i].grade = rdat[i];
199 }
200 break;
wdenkaffae2b2002-08-17 09:36:01 +0000201
wdenkb00ec162003-06-19 23:40:20 +0000202 case HYMOD_EEREC_CPUTYP: /* CPU type */
203 if (rlen == 1)
204 ep->mpc.type = *rdat;
205 break;
wdenkaffae2b2002-08-17 09:36:01 +0000206
wdenkb00ec162003-06-19 23:40:20 +0000207 case HYMOD_EEREC_CPUSPD: /* CPU speed */
208 if (rlen == 1)
209 ep->mpc.cpuspd = *rdat;
210 break;
wdenkaffae2b2002-08-17 09:36:01 +0000211
wdenkb00ec162003-06-19 23:40:20 +0000212 case HYMOD_EEREC_CPMSPD: /* CPM speed */
213 if (rlen == 1)
214 ep->mpc.cpmspd = *rdat;
215 break;
wdenkaffae2b2002-08-17 09:36:01 +0000216
wdenkb00ec162003-06-19 23:40:20 +0000217 case HYMOD_EEREC_BUSSPD: /* bus speed */
218 if (rlen == 1)
219 ep->mpc.busspd = *rdat;
220 break;
wdenkaffae2b2002-08-17 09:36:01 +0000221
wdenkb00ec162003-06-19 23:40:20 +0000222 case HYMOD_EEREC_HSTYPE: /* hs-serial chip type */
223 if (rlen == 1)
224 ep->hss.type = *rdat;
225 break;
wdenkaffae2b2002-08-17 09:36:01 +0000226
wdenkb00ec162003-06-19 23:40:20 +0000227 case HYMOD_EEREC_HSCHIN: /* num hs-serial input chans */
228 if (rlen == 1)
229 ep->hss.nchin = *rdat;
230 break;
wdenkaffae2b2002-08-17 09:36:01 +0000231
wdenkb00ec162003-06-19 23:40:20 +0000232 case HYMOD_EEREC_HSCHOUT: /* num hs-serial output chans */
233 if (rlen == 1)
234 ep->hss.nchout = *rdat;
235 break;
wdenkaffae2b2002-08-17 09:36:01 +0000236
wdenkb00ec162003-06-19 23:40:20 +0000237 default: /* ignore */
238 break;
239 }
wdenkaffae2b2002-08-17 09:36:01 +0000240 }
wdenkaffae2b2002-08-17 09:36:01 +0000241
wdenkb00ec162003-06-19 23:40:20 +0000242 return (1);
wdenkaffae2b2002-08-17 09:36:01 +0000243}
244
245/* maps an ascii "name=value" into a binary eeprom data record */
246typedef
wdenkb00ec162003-06-19 23:40:20 +0000247 struct _eerec_map {
248 char *name;
249 uint type;
250 uchar *(*handler) \
251 (struct _eerec_map *, uchar *, uchar *, uchar *);
252 uint length;
253 uint maxlen;
254 }
wdenkaffae2b2002-08-17 09:36:01 +0000255eerec_map_t;
256
257static uchar *
wdenkb00ec162003-06-19 23:40:20 +0000258uint_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
wdenkaffae2b2002-08-17 09:36:01 +0000259{
wdenkdbae5042003-06-21 00:17:24 +0000260 char *eval;
261 ulong lval;
wdenkaffae2b2002-08-17 09:36:01 +0000262
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200263 lval = simple_strtol ((char *)val, &eval, 10);
wdenkaffae2b2002-08-17 09:36:01 +0000264
wdenkdbae5042003-06-21 00:17:24 +0000265 if ((uchar *)eval == val || *eval != '\0') {
266 printf ("%s rec (%s) is not a valid uint\n", rp->name, val);
wdenkb00ec162003-06-19 23:40:20 +0000267 return (NULL);
268 }
wdenkaffae2b2002-08-17 09:36:01 +0000269
wdenkb00ec162003-06-19 23:40:20 +0000270 if (dp + 2 + rp->length > edp) {
271 printf ("can't fit %s rec into eeprom\n", rp->name);
272 return (NULL);
273 }
wdenkaffae2b2002-08-17 09:36:01 +0000274
wdenkb00ec162003-06-19 23:40:20 +0000275 *dp++ = rp->type;
276 *dp++ = rp->length;
wdenkaffae2b2002-08-17 09:36:01 +0000277
wdenkb00ec162003-06-19 23:40:20 +0000278 switch (rp->length) {
wdenkaffae2b2002-08-17 09:36:01 +0000279
wdenkb00ec162003-06-19 23:40:20 +0000280 case 1:
wdenkdbae5042003-06-21 00:17:24 +0000281 if (lval >= 256) {
wdenkb00ec162003-06-19 23:40:20 +0000282 printf ("%s rec value (%lu) out of range (0-255)\n",
wdenkdbae5042003-06-21 00:17:24 +0000283 rp->name, lval);
wdenkb00ec162003-06-19 23:40:20 +0000284 return (NULL);
285 }
wdenkdbae5042003-06-21 00:17:24 +0000286 *dp++ = lval;
wdenkb00ec162003-06-19 23:40:20 +0000287 break;
wdenkaffae2b2002-08-17 09:36:01 +0000288
wdenkb00ec162003-06-19 23:40:20 +0000289 case 2:
wdenkdbae5042003-06-21 00:17:24 +0000290 if (lval >= 65536) {
wdenkb00ec162003-06-19 23:40:20 +0000291 printf ("%s rec value (%lu) out of range (0-65535)\n",
wdenkdbae5042003-06-21 00:17:24 +0000292 rp->name, lval);
wdenkb00ec162003-06-19 23:40:20 +0000293 return (NULL);
294 }
wdenkdbae5042003-06-21 00:17:24 +0000295 *dp++ = lval >> 8;
296 *dp++ = lval;
wdenkb00ec162003-06-19 23:40:20 +0000297 break;
wdenkaffae2b2002-08-17 09:36:01 +0000298
wdenkb00ec162003-06-19 23:40:20 +0000299 case 4:
wdenkdbae5042003-06-21 00:17:24 +0000300 *dp++ = lval >> 24;
301 *dp++ = lval >> 16;
302 *dp++ = lval >> 8;
303 *dp++ = lval;
wdenkb00ec162003-06-19 23:40:20 +0000304 break;
wdenkaffae2b2002-08-17 09:36:01 +0000305
wdenkb00ec162003-06-19 23:40:20 +0000306 default:
307 printf ("huh? rp->length not 1, 2 or 4! (%d)\n", rp->length);
308 return (NULL);
309 }
wdenkaffae2b2002-08-17 09:36:01 +0000310
wdenkb00ec162003-06-19 23:40:20 +0000311 return (dp);
wdenkaffae2b2002-08-17 09:36:01 +0000312}
313
314static uchar *
wdenkb00ec162003-06-19 23:40:20 +0000315date_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
wdenkaffae2b2002-08-17 09:36:01 +0000316{
wdenkb00ec162003-06-19 23:40:20 +0000317 hymod_date_t date;
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200318 char *p = (char *)val;
wdenkdbae5042003-06-21 00:17:24 +0000319 char *ep;
320 ulong lval;
wdenkaffae2b2002-08-17 09:36:01 +0000321
wdenkdbae5042003-06-21 00:17:24 +0000322 lval = simple_strtol (p, &ep, 10);
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200323 if (ep == p || *ep++ != '-') {
wdenkaffae2b2002-08-17 09:36:01 +0000324bad_date:
wdenkb00ec162003-06-19 23:40:20 +0000325 printf ("%s rec (%s) is not a valid date\n", rp->name, val);
326 return (NULL);
327 }
wdenkdbae5042003-06-21 00:17:24 +0000328 if (lval >= 65536)
329 goto bad_date;
330 date.year = lval;
wdenkaffae2b2002-08-17 09:36:01 +0000331
wdenkdbae5042003-06-21 00:17:24 +0000332 lval = simple_strtol (p = ep, &ep, 10);
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200333 if (ep == p || *ep++ != '-' || lval == 0 || lval > 12)
wdenkb00ec162003-06-19 23:40:20 +0000334 goto bad_date;
wdenkdbae5042003-06-21 00:17:24 +0000335 date.month = lval;
wdenkaffae2b2002-08-17 09:36:01 +0000336
wdenkdbae5042003-06-21 00:17:24 +0000337 lval = simple_strtol (p = ep, &ep, 10);
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200338 if (ep == p || *ep != '\0' || lval == 0 || lval > 31)
wdenkb00ec162003-06-19 23:40:20 +0000339 goto bad_date;
wdenkdbae5042003-06-21 00:17:24 +0000340 date.day = lval;
wdenkaffae2b2002-08-17 09:36:01 +0000341
wdenkdbae5042003-06-21 00:17:24 +0000342 if (dp + 2 + rp->length > edp) {
wdenkb00ec162003-06-19 23:40:20 +0000343 printf ("can't fit %s rec into eeprom\n", rp->name);
344 return (NULL);
345 }
wdenkaffae2b2002-08-17 09:36:01 +0000346
wdenkb00ec162003-06-19 23:40:20 +0000347 *dp++ = rp->type;
wdenkdbae5042003-06-21 00:17:24 +0000348 *dp++ = rp->length;
349 *dp++ = date.year >> 8;
350 *dp++ = date.year;
351 *dp++ = date.month;
352 *dp++ = date.day;
wdenkaffae2b2002-08-17 09:36:01 +0000353
wdenkb00ec162003-06-19 23:40:20 +0000354 return (dp);
wdenkaffae2b2002-08-17 09:36:01 +0000355}
356
357static uchar *
wdenkb00ec162003-06-19 23:40:20 +0000358string_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
wdenkaffae2b2002-08-17 09:36:01 +0000359{
wdenkb00ec162003-06-19 23:40:20 +0000360 uint len;
wdenkaffae2b2002-08-17 09:36:01 +0000361
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200362 if ((len = strlen ((char *)val)) > rp->maxlen) {
wdenkb00ec162003-06-19 23:40:20 +0000363 printf ("%s rec (%s) string is too long (%d>%d)\n",
364 rp->name, val, len, rp->maxlen);
365 return (NULL);
366 }
wdenkaffae2b2002-08-17 09:36:01 +0000367
wdenkb00ec162003-06-19 23:40:20 +0000368 if (dp + 2 + len > edp) {
369 printf ("can't fit %s rec into eeprom\n", rp->name);
370 return (NULL);
371 }
wdenkaffae2b2002-08-17 09:36:01 +0000372
wdenkb00ec162003-06-19 23:40:20 +0000373 *dp++ = rp->type;
374 *dp++ = len;
375 memcpy (dp, val, len);
376 dp += len;
wdenkaffae2b2002-08-17 09:36:01 +0000377
wdenkb00ec162003-06-19 23:40:20 +0000378 return (dp);
wdenkaffae2b2002-08-17 09:36:01 +0000379}
380
381static uchar *
wdenkb00ec162003-06-19 23:40:20 +0000382bytes_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
wdenkaffae2b2002-08-17 09:36:01 +0000383{
wdenkdbae5042003-06-21 00:17:24 +0000384 uchar bytes[HYMOD_MAX_BYTES], nbytes, *p;
385 char *ep;
wdenkaffae2b2002-08-17 09:36:01 +0000386
wdenkdbae5042003-06-21 00:17:24 +0000387 for (nbytes = 0, p = val; *p != '\0'; p = (uchar *)ep) {
388 ulong lval;
wdenkaffae2b2002-08-17 09:36:01 +0000389
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200390 lval = simple_strtol ((char *)p, &ep, 10);
wdenkdbae5042003-06-21 00:17:24 +0000391 if ((uchar *)ep == p || (*ep != '\0' && *ep != ',') || \
392 lval >= 256) {
393 printf ("%s rec (%s) byte array has invalid uint\n",
wdenkb00ec162003-06-19 23:40:20 +0000394 rp->name, val);
395 return (NULL);
396 }
wdenkdbae5042003-06-21 00:17:24 +0000397 if (nbytes >= HYMOD_MAX_BYTES) {
398 printf ("%s rec (%s) byte array too long\n",
wdenkb00ec162003-06-19 23:40:20 +0000399 rp->name, val);
400 return (NULL);
401 }
wdenkdbae5042003-06-21 00:17:24 +0000402 bytes[nbytes++] = lval;
wdenkaffae2b2002-08-17 09:36:01 +0000403
wdenkdbae5042003-06-21 00:17:24 +0000404 if (*ep != '\0')
405 ep++;
wdenkb00ec162003-06-19 23:40:20 +0000406 }
wdenkaffae2b2002-08-17 09:36:01 +0000407
wdenkb00ec162003-06-19 23:40:20 +0000408 if (dp + 2 + nbytes > edp) {
409 printf ("can't fit %s rec into eeprom\n", rp->name);
410 return (NULL);
411 }
wdenkaffae2b2002-08-17 09:36:01 +0000412
wdenkb00ec162003-06-19 23:40:20 +0000413 *dp++ = rp->type;
414 *dp++ = nbytes;
415 memcpy (dp, bytes, nbytes);
416 dp += nbytes;
wdenkaffae2b2002-08-17 09:36:01 +0000417
wdenkb00ec162003-06-19 23:40:20 +0000418 return (dp);
wdenkaffae2b2002-08-17 09:36:01 +0000419}
420
421static eerec_map_t eerec_map[] = {
wdenkb00ec162003-06-19 23:40:20 +0000422 /* name type handler len max */
423 { "serno", HYMOD_EEREC_SERNO, uint_handler, 4, 0 },
424 { "date", HYMOD_EEREC_DATE, date_handler, 4, 0 },
425 { "batch", HYMOD_EEREC_BATCH, string_handler, 0, HYMOD_MAX_BATCH },
426 { "type", HYMOD_EEREC_TYPE, uint_handler, 1, 0 },
427 { "rev", HYMOD_EEREC_REV, uint_handler, 1, 0 },
428 { "sdram", HYMOD_EEREC_SDRAM, bytes_handler, 0, HYMOD_MAX_SDRAM },
429 { "flash", HYMOD_EEREC_FLASH, bytes_handler, 0, HYMOD_MAX_FLASH },
430 { "zbt", HYMOD_EEREC_ZBT, bytes_handler, 0, HYMOD_MAX_ZBT },
431 { "xlxtyp", HYMOD_EEREC_XLXTYP, bytes_handler, 0, HYMOD_MAX_XLX },
432 { "xlxspd", HYMOD_EEREC_XLXSPD, bytes_handler, 0, HYMOD_MAX_XLX },
433 { "xlxtmp", HYMOD_EEREC_XLXTMP, bytes_handler, 0, HYMOD_MAX_XLX },
434 { "xlxgrd", HYMOD_EEREC_XLXGRD, bytes_handler, 0, HYMOD_MAX_XLX },
435 { "cputyp", HYMOD_EEREC_CPUTYP, uint_handler, 1, 0 },
436 { "cpuspd", HYMOD_EEREC_CPUSPD, uint_handler, 1, 0 },
437 { "cpmspd", HYMOD_EEREC_CPMSPD, uint_handler, 1, 0 },
438 { "busspd", HYMOD_EEREC_BUSSPD, uint_handler, 1, 0 },
439 { "hstype", HYMOD_EEREC_HSTYPE, uint_handler, 1, 0 },
440 { "hschin", HYMOD_EEREC_HSCHIN, uint_handler, 1, 0 },
441 { "hschout", HYMOD_EEREC_HSCHOUT, uint_handler, 1, 0 },
wdenkaffae2b2002-08-17 09:36:01 +0000442};
443
444static int neerecs = sizeof eerec_map / sizeof eerec_map[0];
445
446static uchar data[HYMOD_EEPROM_SIZE], *sdp, *dp, *edp;
447
448static int
wdenkb00ec162003-06-19 23:40:20 +0000449eerec_callback (uchar *name, uchar *val)
wdenkaffae2b2002-08-17 09:36:01 +0000450{
wdenkb00ec162003-06-19 23:40:20 +0000451 eerec_map_t *rp;
wdenkaffae2b2002-08-17 09:36:01 +0000452
wdenkb00ec162003-06-19 23:40:20 +0000453 for (rp = eerec_map; rp < &eerec_map[neerecs]; rp++)
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200454 if (strcmp ((char *)name, rp->name) == 0)
wdenkb00ec162003-06-19 23:40:20 +0000455 break;
wdenkaffae2b2002-08-17 09:36:01 +0000456
wdenkb00ec162003-06-19 23:40:20 +0000457 if (rp >= &eerec_map[neerecs])
458 return (0);
wdenkaffae2b2002-08-17 09:36:01 +0000459
wdenkb00ec162003-06-19 23:40:20 +0000460 if ((dp = (*rp->handler) (rp, val, dp, edp)) == NULL)
461 return (0);
wdenkaffae2b2002-08-17 09:36:01 +0000462
wdenkb00ec162003-06-19 23:40:20 +0000463 return (1);
wdenkaffae2b2002-08-17 09:36:01 +0000464}
465
wdenkb00ec162003-06-19 23:40:20 +0000466static int
467hymod_eeprom_fetch(int which, char *filename, ulong addr)
wdenkaffae2b2002-08-17 09:36:01 +0000468{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200469 unsigned dev_addr = CONFIG_SYS_I2C_EEPROM_ADDR | \
wdenkb00ec162003-06-19 23:40:20 +0000470 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
471 hymod_eehdr_t *hp = (hymod_eehdr_t *)&data[0];
472 ulong crc;
wdenkaffae2b2002-08-17 09:36:01 +0000473
wdenkdbae5042003-06-21 00:17:24 +0000474 memset (hp, 0, sizeof *hp);
wdenkb00ec162003-06-19 23:40:20 +0000475 hp->id = HYMOD_EEPROM_ID;
476 hp->ver = HYMOD_EEPROM_VER;
wdenkaffae2b2002-08-17 09:36:01 +0000477
wdenkb00ec162003-06-19 23:40:20 +0000478 dp = sdp = (uchar *)(hp + 1);
479 edp = dp + HYMOD_EEPROM_MAXLEN;
wdenkaffae2b2002-08-17 09:36:01 +0000480
wdenkb00ec162003-06-19 23:40:20 +0000481 if (fetch_and_parse (filename, addr, eerec_callback) == 0)
482 return (0);
wdenkaffae2b2002-08-17 09:36:01 +0000483
wdenkb00ec162003-06-19 23:40:20 +0000484 hp->len = dp - sdp;
wdenkaffae2b2002-08-17 09:36:01 +0000485
wdenkb00ec162003-06-19 23:40:20 +0000486 crc = crc32 (0, data, dp - data);
487 memcpy (dp, &crc, sizeof (ulong));
488 dp += sizeof (ulong);
wdenkaffae2b2002-08-17 09:36:01 +0000489
wdenkb00ec162003-06-19 23:40:20 +0000490 eeprom_write (dev_addr, 0, data, dp - data);
wdenkaffae2b2002-08-17 09:36:01 +0000491
wdenkb00ec162003-06-19 23:40:20 +0000492 return (1);
wdenkaffae2b2002-08-17 09:36:01 +0000493}
494
495static char *type_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000496 "NONE", "IO", "CLP", "DSP", "INPUT", "ALT-INPUT", "DISPLAY"
wdenkaffae2b2002-08-17 09:36:01 +0000497};
498
499static char *xlxtyp_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000500 "NONE", "XCV300E", "XCV400E", "XCV600E"
wdenkaffae2b2002-08-17 09:36:01 +0000501};
502
503static char *xlxspd_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000504 "NONE", "6", "7", "8"
wdenkaffae2b2002-08-17 09:36:01 +0000505};
506
507static char *xlxtmp_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000508 "NONE", "COM", "IND"
wdenkaffae2b2002-08-17 09:36:01 +0000509};
510
511static char *xlxgrd_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000512 "NONE", "NORMAL", "ENGSAMP"
wdenkaffae2b2002-08-17 09:36:01 +0000513};
514
515static char *cputyp_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000516 "NONE", "MPC8260"
wdenkaffae2b2002-08-17 09:36:01 +0000517};
518
519static char *clk_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000520 "NONE", "33", "66", "100", "133", "166", "200"
wdenkaffae2b2002-08-17 09:36:01 +0000521};
522
523static char *hstype_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000524 "NONE", "AMCC-S2064A"
wdenkaffae2b2002-08-17 09:36:01 +0000525};
526
527static void
wdenkb00ec162003-06-19 23:40:20 +0000528print_mem (char *l, char *s, uchar n, uchar a[])
wdenkaffae2b2002-08-17 09:36:01 +0000529{
wdenkb00ec162003-06-19 23:40:20 +0000530 if (n > 0) {
531 if (n == 1)
532 printf ("%s%dMB %s", s, 1 << (a[0] - 20), l);
533 else {
534 ulong t = 0;
535 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000536
wdenkb00ec162003-06-19 23:40:20 +0000537 for (i = 0; i < n; i++)
538 t += 1 << (a[i] - 20);
wdenkaffae2b2002-08-17 09:36:01 +0000539
wdenkb00ec162003-06-19 23:40:20 +0000540 printf ("%s%luMB %s (%d banks:", s, t, l, n);
wdenkaffae2b2002-08-17 09:36:01 +0000541
wdenkb00ec162003-06-19 23:40:20 +0000542 for (i = 0; i < n; i++)
543 printf ("%dMB%s",
544 1 << (a[i] - 20),
545 (i == n - 1) ? ")" : ",");
546 }
wdenkaffae2b2002-08-17 09:36:01 +0000547 }
wdenkb00ec162003-06-19 23:40:20 +0000548 else
549 printf ("%sNO %s", s, l);
wdenkaffae2b2002-08-17 09:36:01 +0000550}
551
552void
wdenkb00ec162003-06-19 23:40:20 +0000553hymod_eeprom_print (hymod_eeprom_t *ep)
wdenkaffae2b2002-08-17 09:36:01 +0000554{
wdenkb00ec162003-06-19 23:40:20 +0000555 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000556
wdenkb00ec162003-06-19 23:40:20 +0000557 printf (" Hymod %s board, rev %03d\n",
558 type_vals[ep->bdtype], ep->bdrev);
wdenkaffae2b2002-08-17 09:36:01 +0000559
wdenkb00ec162003-06-19 23:40:20 +0000560 printf (" serial #: %010lu, date %04d-%02d-%02d",
561 ep->serno, ep->date.year, ep->date.month, ep->date.day);
562 if (ep->batchlen > 0)
563 printf (", batch \"%.*s\"", ep->batchlen, ep->batch);
564 puts ("\n");
wdenkaffae2b2002-08-17 09:36:01 +0000565
wdenkb00ec162003-06-19 23:40:20 +0000566 switch (ep->bdtype) {
wdenkaffae2b2002-08-17 09:36:01 +0000567
wdenkb00ec162003-06-19 23:40:20 +0000568 case HYMOD_BDTYPE_IO:
569 case HYMOD_BDTYPE_CLP:
570 case HYMOD_BDTYPE_DSP:
571 printf (" Motorola %s CPU, speeds: %s/%s/%s",
572 cputyp_vals[ep->mpc.type], clk_vals[ep->mpc.cpuspd],
573 clk_vals[ep->mpc.cpmspd], clk_vals[ep->mpc.busspd]);
wdenkaffae2b2002-08-17 09:36:01 +0000574
wdenkb00ec162003-06-19 23:40:20 +0000575 print_mem ("SDRAM", ", ", ep->nsdram, ep->sdramsz);
wdenkaffae2b2002-08-17 09:36:01 +0000576
wdenkb00ec162003-06-19 23:40:20 +0000577 print_mem ("FLASH", ", ", ep->nflash, ep->flashsz);
wdenkaffae2b2002-08-17 09:36:01 +0000578
wdenkb00ec162003-06-19 23:40:20 +0000579 puts ("\n");
wdenkaffae2b2002-08-17 09:36:01 +0000580
wdenkb00ec162003-06-19 23:40:20 +0000581 print_mem ("ZBT", " ", ep->nzbt, ep->zbtsz);
wdenkaffae2b2002-08-17 09:36:01 +0000582
wdenkb00ec162003-06-19 23:40:20 +0000583 if (ep->nxlx > 0) {
584 hymod_xlx_t *xp;
wdenkaffae2b2002-08-17 09:36:01 +0000585
wdenkb00ec162003-06-19 23:40:20 +0000586 if (ep->nxlx == 1) {
587 xp = &ep->xlx[0];
588 printf (", Xilinx %s FPGA (%s/%s/%s)",
589 xlxtyp_vals[xp->type],
590 xlxspd_vals[xp->speed],
591 xlxtmp_vals[xp->temp],
592 xlxgrd_vals[xp->grade]);
593 }
594 else {
595 printf (", %d Xilinx FPGAs (", ep->nxlx);
596 for (i = 0; i < ep->nxlx; i++) {
597 xp = &ep->xlx[i];
598 printf ("%s[%s/%s/%s]%s",
599 xlxtyp_vals[xp->type],
600 xlxspd_vals[xp->speed],
601 xlxtmp_vals[xp->temp],
602 xlxgrd_vals[xp->grade],
603 (i == ep->nxlx - 1) ? ")" : ", ");
604 }
605 }
wdenkaffae2b2002-08-17 09:36:01 +0000606 }
wdenkb00ec162003-06-19 23:40:20 +0000607 else
608 puts(", NO FPGAs");
609
610 puts ("\n");
611
612 if (ep->hss.type > 0)
613 printf (" High Speed Serial: "
614 "%s, %d input%s, %d output%s\n",
615 hstype_vals[ep->hss.type],
616 ep->hss.nchin,
617 (ep->hss.nchin == 1 ? "" : "s"),
618 ep->hss.nchout,
619 (ep->hss.nchout == 1 ? "" : "s"));
620 break;
621
622 case HYMOD_BDTYPE_INPUT:
623 case HYMOD_BDTYPE_ALTINPUT:
624 case HYMOD_BDTYPE_DISPLAY:
625 break;
626
627 default:
628 /* crap! */
629 printf (" UNKNOWN BOARD TYPE: %d\n", ep->bdtype);
630 break;
wdenkaffae2b2002-08-17 09:36:01 +0000631 }
wdenkb00ec162003-06-19 23:40:20 +0000632}
wdenkaffae2b2002-08-17 09:36:01 +0000633
wdenkb00ec162003-06-19 23:40:20 +0000634int
635hymod_eeprom_read (int which, hymod_eeprom_t *ep)
636{
637 char *label = which ? "mezzanine" : "main";
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200638 unsigned dev_addr = CONFIG_SYS_I2C_EEPROM_ADDR | \
wdenkb00ec162003-06-19 23:40:20 +0000639 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
640 char filename[50], prompt[50], *dir;
641 int serno, count = 0, rc;
wdenkaffae2b2002-08-17 09:36:01 +0000642
wdenkb00ec162003-06-19 23:40:20 +0000643 rc = eeprom_probe (dev_addr, 0);
wdenkaffae2b2002-08-17 09:36:01 +0000644
wdenkb00ec162003-06-19 23:40:20 +0000645 if (rc > 0) {
646 printf ("*** probe for eeprom failed with code %d\n", rc);
647 return (0);
648 }
649
650 if (rc < 0)
651 return (rc);
652
653 sprintf (prompt, "Enter %s board serial number: ", label);
wdenkaffae2b2002-08-17 09:36:01 +0000654
wdenkb00ec162003-06-19 23:40:20 +0000655 if ((dir = getenv ("bddb_cfgdir")) == NULL)
656 dir = def_bddb_cfgdir;
657
658 for (;;) {
659 int rc;
660
661 if (hymod_eeprom_load (which, ep))
662 return (1);
663
664 printf ("*** %s board EEPROM contents are %sinvalid\n",
665 label, count == 0 ? "" : "STILL ");
666
667 puts ("*** will fetch from server (Ctrl-C to abort)\n");
668
669 serno = hymod_get_serno (prompt);
670
671 if (serno < 0) {
672 if (serno == -1)
673 puts ("\n*** interrupted!");
674 else
675 puts ("\n*** timeout!");
676 puts (" - ignoring eeprom contents\n");
677 return (0);
678 }
679
680 sprintf (filename, "%s/%010d.cfg", dir, serno);
681
682 printf ("*** fetching %s board EEPROM contents from server\n",
683 label);
684
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200685 rc = hymod_eeprom_fetch (which, filename, CONFIG_SYS_LOAD_ADDR);
wdenkb00ec162003-06-19 23:40:20 +0000686
687 if (rc == 0) {
688 puts ("*** fetch failed - ignoring eeprom contents\n");
689 return (0);
690 }
691
692 count++;
693 }
wdenkaffae2b2002-08-17 09:36:01 +0000694}