blob: ffb0df197683a4437ca923de2b3613f62e085c96 [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 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +00006 */
7
8#include <common.h>
9#include <mpc8260.h>
10
11/* imports from fetch.c */
wdenkb00ec162003-06-19 23:40:20 +000012extern int fetch_and_parse (char *, ulong, int (*)(uchar *, uchar *));
wdenkaffae2b2002-08-17 09:36:01 +000013
wdenkb00ec162003-06-19 23:40:20 +000014/* imports from input.c */
15extern int hymod_get_serno (const char *);
16
17/* this is relative to the root of the server's tftp directory */
18static char *def_bddb_cfgdir = "/hymod/bddb";
19
20static int
21hymod_eeprom_load (int which, hymod_eeprom_t *ep)
wdenkaffae2b2002-08-17 09:36:01 +000022{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020023 unsigned dev_addr = CONFIG_SYS_I2C_EEPROM_ADDR | \
wdenkb00ec162003-06-19 23:40:20 +000024 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
25 unsigned offset = 0;
wdenkdbae5042003-06-21 00:17:24 +000026 uchar data[HYMOD_EEPROM_MAXLEN], *dp, *edp;
27 hymod_eehdr_t hdr;
wdenkb00ec162003-06-19 23:40:20 +000028 ulong len, crc;
wdenkaffae2b2002-08-17 09:36:01 +000029
wdenkb00ec162003-06-19 23:40:20 +000030 memset (ep, 0, sizeof *ep);
wdenkaffae2b2002-08-17 09:36:01 +000031
wdenkdbae5042003-06-21 00:17:24 +000032 eeprom_read (dev_addr, offset, (uchar *)&hdr, sizeof (hdr));
33 offset += sizeof (hdr);
wdenkaffae2b2002-08-17 09:36:01 +000034
wdenkdbae5042003-06-21 00:17:24 +000035 if (hdr.id != HYMOD_EEPROM_ID || hdr.ver > HYMOD_EEPROM_VER ||
36 (len = hdr.len) > HYMOD_EEPROM_MAXLEN)
wdenkb00ec162003-06-19 23:40:20 +000037 return (0);
wdenkaffae2b2002-08-17 09:36:01 +000038
wdenkdbae5042003-06-21 00:17:24 +000039 eeprom_read (dev_addr, offset, data, len);
wdenkb00ec162003-06-19 23:40:20 +000040 offset += len;
wdenkaffae2b2002-08-17 09:36:01 +000041
wdenkb00ec162003-06-19 23:40:20 +000042 eeprom_read (dev_addr, offset, (uchar *)&crc, sizeof (ulong));
wdenkdbae5042003-06-21 00:17:24 +000043 offset += sizeof (ulong);
wdenkaffae2b2002-08-17 09:36:01 +000044
Wolfgang Denk7fb52662005-10-13 16:45:02 +020045 if (crc32 (crc32 (0, (uchar *)&hdr, sizeof hdr), data, len) != crc)
wdenkb00ec162003-06-19 23:40:20 +000046 return (0);
wdenkaffae2b2002-08-17 09:36:01 +000047
wdenkdbae5042003-06-21 00:17:24 +000048 ep->ver = hdr.ver;
49 dp = data; edp = dp + len;
wdenkaffae2b2002-08-17 09:36:01 +000050
wdenkb00ec162003-06-19 23:40:20 +000051 for (;;) {
wdenkb00ec162003-06-19 23:40:20 +000052 ulong rtyp;
53 uchar rlen, *rdat;
wdenkaffae2b2002-08-17 09:36:01 +000054
wdenkdbae5042003-06-21 00:17:24 +000055 rtyp = *dp++;
56 if ((rtyp & 0x80) == 0)
57 rlen = *dp++;
wdenkb00ec162003-06-19 23:40:20 +000058 else {
wdenkdbae5042003-06-21 00:17:24 +000059 uchar islarge = rtyp & 0x40;
60
61 rtyp = ((rtyp & 0x3f) << 8) | *dp++;
62 if (islarge) {
63 rtyp = (rtyp << 8) | *dp++;
64 rtyp = (rtyp << 8) | *dp++;
65 }
66
67 rlen = *dp++;
68 rlen = (rlen << 8) | *dp++;
69 if (islarge) {
70 rlen = (rlen << 8) | *dp++;
71 rlen = (rlen << 8) | *dp++;
72 }
wdenkb00ec162003-06-19 23:40:20 +000073 }
wdenkaffae2b2002-08-17 09:36:01 +000074
wdenkb00ec162003-06-19 23:40:20 +000075 if (rtyp == 0)
76 break;
wdenkaffae2b2002-08-17 09:36:01 +000077
wdenkdbae5042003-06-21 00:17:24 +000078 rdat = dp;
79 dp += rlen;
80
wdenkb00ec162003-06-19 23:40:20 +000081 if (dp > edp) /* error? */
82 break;
wdenkaffae2b2002-08-17 09:36:01 +000083
wdenkb00ec162003-06-19 23:40:20 +000084 switch (rtyp) {
wdenkaffae2b2002-08-17 09:36:01 +000085
wdenkb00ec162003-06-19 23:40:20 +000086 case HYMOD_EEREC_SERNO: /* serial number */
87 if (rlen == sizeof (ulong))
wdenkdbae5042003-06-21 00:17:24 +000088 ep->serno = \
89 ((ulong)rdat[0] << 24) | \
90 ((ulong)rdat[1] << 16) | \
91 ((ulong)rdat[2] << 8) | \
92 (ulong)rdat[3];
wdenkb00ec162003-06-19 23:40:20 +000093 break;
wdenkaffae2b2002-08-17 09:36:01 +000094
wdenkb00ec162003-06-19 23:40:20 +000095 case HYMOD_EEREC_DATE: /* date */
wdenkdbae5042003-06-21 00:17:24 +000096 if (rlen == sizeof (hymod_date_t)) {
97 ep->date.year = ((ushort)rdat[0] << 8) | \
98 (ushort)rdat[1];
99 ep->date.month = rdat[2];
100 ep->date.day = rdat[3];
101 }
wdenkb00ec162003-06-19 23:40:20 +0000102 break;
wdenkaffae2b2002-08-17 09:36:01 +0000103
wdenkb00ec162003-06-19 23:40:20 +0000104 case HYMOD_EEREC_BATCH: /* batch */
105 if (rlen <= HYMOD_MAX_BATCH)
106 memcpy (ep->batch, rdat, ep->batchlen = rlen);
107 break;
wdenkaffae2b2002-08-17 09:36:01 +0000108
wdenkb00ec162003-06-19 23:40:20 +0000109 case HYMOD_EEREC_TYPE: /* board type */
110 if (rlen == 1)
111 ep->bdtype = *rdat;
112 break;
wdenkaffae2b2002-08-17 09:36:01 +0000113
wdenkb00ec162003-06-19 23:40:20 +0000114 case HYMOD_EEREC_REV: /* board revision */
115 if (rlen == 1)
116 ep->bdrev = *rdat;
117 break;
wdenkaffae2b2002-08-17 09:36:01 +0000118
wdenkb00ec162003-06-19 23:40:20 +0000119 case HYMOD_EEREC_SDRAM: /* sdram size(s) */
120 if (rlen > 0 && rlen <= HYMOD_MAX_SDRAM) {
121 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000122
wdenkb00ec162003-06-19 23:40:20 +0000123 for (i = 0; i < rlen; i++)
124 ep->sdramsz[i] = rdat[i];
125 ep->nsdram = rlen;
126 }
127 break;
wdenkaffae2b2002-08-17 09:36:01 +0000128
wdenkb00ec162003-06-19 23:40:20 +0000129 case HYMOD_EEREC_FLASH: /* flash size(s) */
130 if (rlen > 0 && rlen <= HYMOD_MAX_FLASH) {
131 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000132
wdenkb00ec162003-06-19 23:40:20 +0000133 for (i = 0; i < rlen; i++)
134 ep->flashsz[i] = rdat[i];
135 ep->nflash = rlen;
136 }
137 break;
wdenkaffae2b2002-08-17 09:36:01 +0000138
wdenkb00ec162003-06-19 23:40:20 +0000139 case HYMOD_EEREC_ZBT: /* zbt ram size(s) */
140 if (rlen > 0 && rlen <= HYMOD_MAX_ZBT) {
141 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000142
wdenkb00ec162003-06-19 23:40:20 +0000143 for (i = 0; i < rlen; i++)
144 ep->zbtsz[i] = rdat[i];
145 ep->nzbt = rlen;
146 }
147 break;
wdenkaffae2b2002-08-17 09:36:01 +0000148
wdenkb00ec162003-06-19 23:40:20 +0000149 case HYMOD_EEREC_XLXTYP: /* xilinx fpga type(s) */
150 if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
151 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000152
wdenkb00ec162003-06-19 23:40:20 +0000153 for (i = 0; i < rlen; i++)
154 ep->xlx[i].type = rdat[i];
155 ep->nxlx = rlen;
156 }
157 break;
wdenkaffae2b2002-08-17 09:36:01 +0000158
wdenkb00ec162003-06-19 23:40:20 +0000159 case HYMOD_EEREC_XLXSPD: /* xilinx fpga speed(s) */
160 if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
161 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000162
wdenkb00ec162003-06-19 23:40:20 +0000163 for (i = 0; i < rlen; i++)
164 ep->xlx[i].speed = rdat[i];
165 }
166 break;
wdenkaffae2b2002-08-17 09:36:01 +0000167
wdenkb00ec162003-06-19 23:40:20 +0000168 case HYMOD_EEREC_XLXTMP: /* xilinx fpga temperature(s) */
169 if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
170 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000171
wdenkb00ec162003-06-19 23:40:20 +0000172 for (i = 0; i < rlen; i++)
173 ep->xlx[i].temp = rdat[i];
174 }
175 break;
wdenkaffae2b2002-08-17 09:36:01 +0000176
wdenkb00ec162003-06-19 23:40:20 +0000177 case HYMOD_EEREC_XLXGRD: /* xilinx fpga grade(s) */
178 if (rlen > 0 && rlen <= HYMOD_MAX_XLX) {
179 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000180
wdenkb00ec162003-06-19 23:40:20 +0000181 for (i = 0; i < rlen; i++)
182 ep->xlx[i].grade = rdat[i];
183 }
184 break;
wdenkaffae2b2002-08-17 09:36:01 +0000185
wdenkb00ec162003-06-19 23:40:20 +0000186 case HYMOD_EEREC_CPUTYP: /* CPU type */
187 if (rlen == 1)
188 ep->mpc.type = *rdat;
189 break;
wdenkaffae2b2002-08-17 09:36:01 +0000190
wdenkb00ec162003-06-19 23:40:20 +0000191 case HYMOD_EEREC_CPUSPD: /* CPU speed */
192 if (rlen == 1)
193 ep->mpc.cpuspd = *rdat;
194 break;
wdenkaffae2b2002-08-17 09:36:01 +0000195
wdenkb00ec162003-06-19 23:40:20 +0000196 case HYMOD_EEREC_CPMSPD: /* CPM speed */
197 if (rlen == 1)
198 ep->mpc.cpmspd = *rdat;
199 break;
wdenkaffae2b2002-08-17 09:36:01 +0000200
wdenkb00ec162003-06-19 23:40:20 +0000201 case HYMOD_EEREC_BUSSPD: /* bus speed */
202 if (rlen == 1)
203 ep->mpc.busspd = *rdat;
204 break;
wdenkaffae2b2002-08-17 09:36:01 +0000205
wdenkb00ec162003-06-19 23:40:20 +0000206 case HYMOD_EEREC_HSTYPE: /* hs-serial chip type */
207 if (rlen == 1)
208 ep->hss.type = *rdat;
209 break;
wdenkaffae2b2002-08-17 09:36:01 +0000210
wdenkb00ec162003-06-19 23:40:20 +0000211 case HYMOD_EEREC_HSCHIN: /* num hs-serial input chans */
212 if (rlen == 1)
213 ep->hss.nchin = *rdat;
214 break;
wdenkaffae2b2002-08-17 09:36:01 +0000215
wdenkb00ec162003-06-19 23:40:20 +0000216 case HYMOD_EEREC_HSCHOUT: /* num hs-serial output chans */
217 if (rlen == 1)
218 ep->hss.nchout = *rdat;
219 break;
wdenkaffae2b2002-08-17 09:36:01 +0000220
wdenkb00ec162003-06-19 23:40:20 +0000221 default: /* ignore */
222 break;
223 }
wdenkaffae2b2002-08-17 09:36:01 +0000224 }
wdenkaffae2b2002-08-17 09:36:01 +0000225
wdenkb00ec162003-06-19 23:40:20 +0000226 return (1);
wdenkaffae2b2002-08-17 09:36:01 +0000227}
228
229/* maps an ascii "name=value" into a binary eeprom data record */
230typedef
wdenkb00ec162003-06-19 23:40:20 +0000231 struct _eerec_map {
232 char *name;
233 uint type;
234 uchar *(*handler) \
235 (struct _eerec_map *, uchar *, uchar *, uchar *);
236 uint length;
237 uint maxlen;
238 }
wdenkaffae2b2002-08-17 09:36:01 +0000239eerec_map_t;
240
241static uchar *
wdenkb00ec162003-06-19 23:40:20 +0000242uint_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
wdenkaffae2b2002-08-17 09:36:01 +0000243{
wdenkdbae5042003-06-21 00:17:24 +0000244 char *eval;
245 ulong lval;
wdenkaffae2b2002-08-17 09:36:01 +0000246
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200247 lval = simple_strtol ((char *)val, &eval, 10);
wdenkaffae2b2002-08-17 09:36:01 +0000248
wdenkdbae5042003-06-21 00:17:24 +0000249 if ((uchar *)eval == val || *eval != '\0') {
250 printf ("%s rec (%s) is not a valid uint\n", rp->name, val);
wdenkb00ec162003-06-19 23:40:20 +0000251 return (NULL);
252 }
wdenkaffae2b2002-08-17 09:36:01 +0000253
wdenkb00ec162003-06-19 23:40:20 +0000254 if (dp + 2 + rp->length > edp) {
255 printf ("can't fit %s rec into eeprom\n", rp->name);
256 return (NULL);
257 }
wdenkaffae2b2002-08-17 09:36:01 +0000258
wdenkb00ec162003-06-19 23:40:20 +0000259 *dp++ = rp->type;
260 *dp++ = rp->length;
wdenkaffae2b2002-08-17 09:36:01 +0000261
wdenkb00ec162003-06-19 23:40:20 +0000262 switch (rp->length) {
wdenkaffae2b2002-08-17 09:36:01 +0000263
wdenkb00ec162003-06-19 23:40:20 +0000264 case 1:
wdenkdbae5042003-06-21 00:17:24 +0000265 if (lval >= 256) {
wdenkb00ec162003-06-19 23:40:20 +0000266 printf ("%s rec value (%lu) out of range (0-255)\n",
wdenkdbae5042003-06-21 00:17:24 +0000267 rp->name, lval);
wdenkb00ec162003-06-19 23:40:20 +0000268 return (NULL);
269 }
wdenkdbae5042003-06-21 00:17:24 +0000270 *dp++ = lval;
wdenkb00ec162003-06-19 23:40:20 +0000271 break;
wdenkaffae2b2002-08-17 09:36:01 +0000272
wdenkb00ec162003-06-19 23:40:20 +0000273 case 2:
wdenkdbae5042003-06-21 00:17:24 +0000274 if (lval >= 65536) {
wdenkb00ec162003-06-19 23:40:20 +0000275 printf ("%s rec value (%lu) out of range (0-65535)\n",
wdenkdbae5042003-06-21 00:17:24 +0000276 rp->name, lval);
wdenkb00ec162003-06-19 23:40:20 +0000277 return (NULL);
278 }
wdenkdbae5042003-06-21 00:17:24 +0000279 *dp++ = lval >> 8;
280 *dp++ = lval;
wdenkb00ec162003-06-19 23:40:20 +0000281 break;
wdenkaffae2b2002-08-17 09:36:01 +0000282
wdenkb00ec162003-06-19 23:40:20 +0000283 case 4:
wdenkdbae5042003-06-21 00:17:24 +0000284 *dp++ = lval >> 24;
285 *dp++ = lval >> 16;
286 *dp++ = lval >> 8;
287 *dp++ = lval;
wdenkb00ec162003-06-19 23:40:20 +0000288 break;
wdenkaffae2b2002-08-17 09:36:01 +0000289
wdenkb00ec162003-06-19 23:40:20 +0000290 default:
291 printf ("huh? rp->length not 1, 2 or 4! (%d)\n", rp->length);
292 return (NULL);
293 }
wdenkaffae2b2002-08-17 09:36:01 +0000294
wdenkb00ec162003-06-19 23:40:20 +0000295 return (dp);
wdenkaffae2b2002-08-17 09:36:01 +0000296}
297
298static uchar *
wdenkb00ec162003-06-19 23:40:20 +0000299date_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
wdenkaffae2b2002-08-17 09:36:01 +0000300{
wdenkb00ec162003-06-19 23:40:20 +0000301 hymod_date_t date;
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200302 char *p = (char *)val;
wdenkdbae5042003-06-21 00:17:24 +0000303 char *ep;
304 ulong lval;
wdenkaffae2b2002-08-17 09:36:01 +0000305
wdenkdbae5042003-06-21 00:17:24 +0000306 lval = simple_strtol (p, &ep, 10);
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200307 if (ep == p || *ep++ != '-') {
wdenkaffae2b2002-08-17 09:36:01 +0000308bad_date:
wdenkb00ec162003-06-19 23:40:20 +0000309 printf ("%s rec (%s) is not a valid date\n", rp->name, val);
310 return (NULL);
311 }
wdenkdbae5042003-06-21 00:17:24 +0000312 if (lval >= 65536)
313 goto bad_date;
314 date.year = lval;
wdenkaffae2b2002-08-17 09:36:01 +0000315
wdenkdbae5042003-06-21 00:17:24 +0000316 lval = simple_strtol (p = ep, &ep, 10);
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200317 if (ep == p || *ep++ != '-' || lval == 0 || lval > 12)
wdenkb00ec162003-06-19 23:40:20 +0000318 goto bad_date;
wdenkdbae5042003-06-21 00:17:24 +0000319 date.month = lval;
wdenkaffae2b2002-08-17 09:36:01 +0000320
wdenkdbae5042003-06-21 00:17:24 +0000321 lval = simple_strtol (p = ep, &ep, 10);
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200322 if (ep == p || *ep != '\0' || lval == 0 || lval > 31)
wdenkb00ec162003-06-19 23:40:20 +0000323 goto bad_date;
wdenkdbae5042003-06-21 00:17:24 +0000324 date.day = lval;
wdenkaffae2b2002-08-17 09:36:01 +0000325
wdenkdbae5042003-06-21 00:17:24 +0000326 if (dp + 2 + rp->length > edp) {
wdenkb00ec162003-06-19 23:40:20 +0000327 printf ("can't fit %s rec into eeprom\n", rp->name);
328 return (NULL);
329 }
wdenkaffae2b2002-08-17 09:36:01 +0000330
wdenkb00ec162003-06-19 23:40:20 +0000331 *dp++ = rp->type;
wdenkdbae5042003-06-21 00:17:24 +0000332 *dp++ = rp->length;
333 *dp++ = date.year >> 8;
334 *dp++ = date.year;
335 *dp++ = date.month;
336 *dp++ = date.day;
wdenkaffae2b2002-08-17 09:36:01 +0000337
wdenkb00ec162003-06-19 23:40:20 +0000338 return (dp);
wdenkaffae2b2002-08-17 09:36:01 +0000339}
340
341static uchar *
wdenkb00ec162003-06-19 23:40:20 +0000342string_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
wdenkaffae2b2002-08-17 09:36:01 +0000343{
wdenkb00ec162003-06-19 23:40:20 +0000344 uint len;
wdenkaffae2b2002-08-17 09:36:01 +0000345
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200346 if ((len = strlen ((char *)val)) > rp->maxlen) {
wdenkb00ec162003-06-19 23:40:20 +0000347 printf ("%s rec (%s) string is too long (%d>%d)\n",
348 rp->name, val, len, rp->maxlen);
349 return (NULL);
350 }
wdenkaffae2b2002-08-17 09:36:01 +0000351
wdenkb00ec162003-06-19 23:40:20 +0000352 if (dp + 2 + len > edp) {
353 printf ("can't fit %s rec into eeprom\n", rp->name);
354 return (NULL);
355 }
wdenkaffae2b2002-08-17 09:36:01 +0000356
wdenkb00ec162003-06-19 23:40:20 +0000357 *dp++ = rp->type;
358 *dp++ = len;
359 memcpy (dp, val, len);
360 dp += len;
wdenkaffae2b2002-08-17 09:36:01 +0000361
wdenkb00ec162003-06-19 23:40:20 +0000362 return (dp);
wdenkaffae2b2002-08-17 09:36:01 +0000363}
364
365static uchar *
wdenkb00ec162003-06-19 23:40:20 +0000366bytes_handler (eerec_map_t *rp, uchar *val, uchar *dp, uchar *edp)
wdenkaffae2b2002-08-17 09:36:01 +0000367{
wdenkdbae5042003-06-21 00:17:24 +0000368 uchar bytes[HYMOD_MAX_BYTES], nbytes, *p;
369 char *ep;
wdenkaffae2b2002-08-17 09:36:01 +0000370
wdenkdbae5042003-06-21 00:17:24 +0000371 for (nbytes = 0, p = val; *p != '\0'; p = (uchar *)ep) {
372 ulong lval;
wdenkaffae2b2002-08-17 09:36:01 +0000373
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200374 lval = simple_strtol ((char *)p, &ep, 10);
wdenkdbae5042003-06-21 00:17:24 +0000375 if ((uchar *)ep == p || (*ep != '\0' && *ep != ',') || \
376 lval >= 256) {
377 printf ("%s rec (%s) byte array has invalid uint\n",
wdenkb00ec162003-06-19 23:40:20 +0000378 rp->name, val);
379 return (NULL);
380 }
wdenkdbae5042003-06-21 00:17:24 +0000381 if (nbytes >= HYMOD_MAX_BYTES) {
382 printf ("%s rec (%s) byte array too long\n",
wdenkb00ec162003-06-19 23:40:20 +0000383 rp->name, val);
384 return (NULL);
385 }
wdenkdbae5042003-06-21 00:17:24 +0000386 bytes[nbytes++] = lval;
wdenkaffae2b2002-08-17 09:36:01 +0000387
wdenkdbae5042003-06-21 00:17:24 +0000388 if (*ep != '\0')
389 ep++;
wdenkb00ec162003-06-19 23:40:20 +0000390 }
wdenkaffae2b2002-08-17 09:36:01 +0000391
wdenkb00ec162003-06-19 23:40:20 +0000392 if (dp + 2 + nbytes > edp) {
393 printf ("can't fit %s rec into eeprom\n", rp->name);
394 return (NULL);
395 }
wdenkaffae2b2002-08-17 09:36:01 +0000396
wdenkb00ec162003-06-19 23:40:20 +0000397 *dp++ = rp->type;
398 *dp++ = nbytes;
399 memcpy (dp, bytes, nbytes);
400 dp += nbytes;
wdenkaffae2b2002-08-17 09:36:01 +0000401
wdenkb00ec162003-06-19 23:40:20 +0000402 return (dp);
wdenkaffae2b2002-08-17 09:36:01 +0000403}
404
405static eerec_map_t eerec_map[] = {
wdenkb00ec162003-06-19 23:40:20 +0000406 /* name type handler len max */
407 { "serno", HYMOD_EEREC_SERNO, uint_handler, 4, 0 },
408 { "date", HYMOD_EEREC_DATE, date_handler, 4, 0 },
409 { "batch", HYMOD_EEREC_BATCH, string_handler, 0, HYMOD_MAX_BATCH },
410 { "type", HYMOD_EEREC_TYPE, uint_handler, 1, 0 },
411 { "rev", HYMOD_EEREC_REV, uint_handler, 1, 0 },
412 { "sdram", HYMOD_EEREC_SDRAM, bytes_handler, 0, HYMOD_MAX_SDRAM },
413 { "flash", HYMOD_EEREC_FLASH, bytes_handler, 0, HYMOD_MAX_FLASH },
414 { "zbt", HYMOD_EEREC_ZBT, bytes_handler, 0, HYMOD_MAX_ZBT },
415 { "xlxtyp", HYMOD_EEREC_XLXTYP, bytes_handler, 0, HYMOD_MAX_XLX },
416 { "xlxspd", HYMOD_EEREC_XLXSPD, bytes_handler, 0, HYMOD_MAX_XLX },
417 { "xlxtmp", HYMOD_EEREC_XLXTMP, bytes_handler, 0, HYMOD_MAX_XLX },
418 { "xlxgrd", HYMOD_EEREC_XLXGRD, bytes_handler, 0, HYMOD_MAX_XLX },
419 { "cputyp", HYMOD_EEREC_CPUTYP, uint_handler, 1, 0 },
420 { "cpuspd", HYMOD_EEREC_CPUSPD, uint_handler, 1, 0 },
421 { "cpmspd", HYMOD_EEREC_CPMSPD, uint_handler, 1, 0 },
422 { "busspd", HYMOD_EEREC_BUSSPD, uint_handler, 1, 0 },
423 { "hstype", HYMOD_EEREC_HSTYPE, uint_handler, 1, 0 },
424 { "hschin", HYMOD_EEREC_HSCHIN, uint_handler, 1, 0 },
425 { "hschout", HYMOD_EEREC_HSCHOUT, uint_handler, 1, 0 },
wdenkaffae2b2002-08-17 09:36:01 +0000426};
427
428static int neerecs = sizeof eerec_map / sizeof eerec_map[0];
429
430static uchar data[HYMOD_EEPROM_SIZE], *sdp, *dp, *edp;
431
432static int
wdenkb00ec162003-06-19 23:40:20 +0000433eerec_callback (uchar *name, uchar *val)
wdenkaffae2b2002-08-17 09:36:01 +0000434{
wdenkb00ec162003-06-19 23:40:20 +0000435 eerec_map_t *rp;
wdenkaffae2b2002-08-17 09:36:01 +0000436
wdenkb00ec162003-06-19 23:40:20 +0000437 for (rp = eerec_map; rp < &eerec_map[neerecs]; rp++)
Wolfgang Denk7fb52662005-10-13 16:45:02 +0200438 if (strcmp ((char *)name, rp->name) == 0)
wdenkb00ec162003-06-19 23:40:20 +0000439 break;
wdenkaffae2b2002-08-17 09:36:01 +0000440
wdenkb00ec162003-06-19 23:40:20 +0000441 if (rp >= &eerec_map[neerecs])
442 return (0);
wdenkaffae2b2002-08-17 09:36:01 +0000443
wdenkb00ec162003-06-19 23:40:20 +0000444 if ((dp = (*rp->handler) (rp, val, dp, edp)) == NULL)
445 return (0);
wdenkaffae2b2002-08-17 09:36:01 +0000446
wdenkb00ec162003-06-19 23:40:20 +0000447 return (1);
wdenkaffae2b2002-08-17 09:36:01 +0000448}
449
wdenkb00ec162003-06-19 23:40:20 +0000450static int
451hymod_eeprom_fetch(int which, char *filename, ulong addr)
wdenkaffae2b2002-08-17 09:36:01 +0000452{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200453 unsigned dev_addr = CONFIG_SYS_I2C_EEPROM_ADDR | \
wdenkb00ec162003-06-19 23:40:20 +0000454 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
455 hymod_eehdr_t *hp = (hymod_eehdr_t *)&data[0];
456 ulong crc;
wdenkaffae2b2002-08-17 09:36:01 +0000457
wdenkdbae5042003-06-21 00:17:24 +0000458 memset (hp, 0, sizeof *hp);
wdenkb00ec162003-06-19 23:40:20 +0000459 hp->id = HYMOD_EEPROM_ID;
460 hp->ver = HYMOD_EEPROM_VER;
wdenkaffae2b2002-08-17 09:36:01 +0000461
wdenkb00ec162003-06-19 23:40:20 +0000462 dp = sdp = (uchar *)(hp + 1);
463 edp = dp + HYMOD_EEPROM_MAXLEN;
wdenkaffae2b2002-08-17 09:36:01 +0000464
wdenkb00ec162003-06-19 23:40:20 +0000465 if (fetch_and_parse (filename, addr, eerec_callback) == 0)
466 return (0);
wdenkaffae2b2002-08-17 09:36:01 +0000467
wdenkb00ec162003-06-19 23:40:20 +0000468 hp->len = dp - sdp;
wdenkaffae2b2002-08-17 09:36:01 +0000469
wdenkb00ec162003-06-19 23:40:20 +0000470 crc = crc32 (0, data, dp - data);
471 memcpy (dp, &crc, sizeof (ulong));
472 dp += sizeof (ulong);
wdenkaffae2b2002-08-17 09:36:01 +0000473
wdenkb00ec162003-06-19 23:40:20 +0000474 eeprom_write (dev_addr, 0, data, dp - data);
wdenkaffae2b2002-08-17 09:36:01 +0000475
wdenkb00ec162003-06-19 23:40:20 +0000476 return (1);
wdenkaffae2b2002-08-17 09:36:01 +0000477}
478
479static char *type_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000480 "NONE", "IO", "CLP", "DSP", "INPUT", "ALT-INPUT", "DISPLAY"
wdenkaffae2b2002-08-17 09:36:01 +0000481};
482
483static char *xlxtyp_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000484 "NONE", "XCV300E", "XCV400E", "XCV600E"
wdenkaffae2b2002-08-17 09:36:01 +0000485};
486
487static char *xlxspd_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000488 "NONE", "6", "7", "8"
wdenkaffae2b2002-08-17 09:36:01 +0000489};
490
491static char *xlxtmp_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000492 "NONE", "COM", "IND"
wdenkaffae2b2002-08-17 09:36:01 +0000493};
494
495static char *xlxgrd_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000496 "NONE", "NORMAL", "ENGSAMP"
wdenkaffae2b2002-08-17 09:36:01 +0000497};
498
499static char *cputyp_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000500 "NONE", "MPC8260"
wdenkaffae2b2002-08-17 09:36:01 +0000501};
502
503static char *clk_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000504 "NONE", "33", "66", "100", "133", "166", "200"
wdenkaffae2b2002-08-17 09:36:01 +0000505};
506
507static char *hstype_vals[] = {
wdenkb00ec162003-06-19 23:40:20 +0000508 "NONE", "AMCC-S2064A"
wdenkaffae2b2002-08-17 09:36:01 +0000509};
510
511static void
wdenkb00ec162003-06-19 23:40:20 +0000512print_mem (char *l, char *s, uchar n, uchar a[])
wdenkaffae2b2002-08-17 09:36:01 +0000513{
wdenkb00ec162003-06-19 23:40:20 +0000514 if (n > 0) {
515 if (n == 1)
516 printf ("%s%dMB %s", s, 1 << (a[0] - 20), l);
517 else {
518 ulong t = 0;
519 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000520
wdenkb00ec162003-06-19 23:40:20 +0000521 for (i = 0; i < n; i++)
522 t += 1 << (a[i] - 20);
wdenkaffae2b2002-08-17 09:36:01 +0000523
wdenkb00ec162003-06-19 23:40:20 +0000524 printf ("%s%luMB %s (%d banks:", s, t, l, n);
wdenkaffae2b2002-08-17 09:36:01 +0000525
wdenkb00ec162003-06-19 23:40:20 +0000526 for (i = 0; i < n; i++)
527 printf ("%dMB%s",
528 1 << (a[i] - 20),
529 (i == n - 1) ? ")" : ",");
530 }
wdenkaffae2b2002-08-17 09:36:01 +0000531 }
wdenkb00ec162003-06-19 23:40:20 +0000532 else
533 printf ("%sNO %s", s, l);
wdenkaffae2b2002-08-17 09:36:01 +0000534}
535
536void
wdenkb00ec162003-06-19 23:40:20 +0000537hymod_eeprom_print (hymod_eeprom_t *ep)
wdenkaffae2b2002-08-17 09:36:01 +0000538{
wdenkb00ec162003-06-19 23:40:20 +0000539 int i;
wdenkaffae2b2002-08-17 09:36:01 +0000540
wdenkb00ec162003-06-19 23:40:20 +0000541 printf (" Hymod %s board, rev %03d\n",
542 type_vals[ep->bdtype], ep->bdrev);
wdenkaffae2b2002-08-17 09:36:01 +0000543
wdenkb00ec162003-06-19 23:40:20 +0000544 printf (" serial #: %010lu, date %04d-%02d-%02d",
545 ep->serno, ep->date.year, ep->date.month, ep->date.day);
546 if (ep->batchlen > 0)
547 printf (", batch \"%.*s\"", ep->batchlen, ep->batch);
548 puts ("\n");
wdenkaffae2b2002-08-17 09:36:01 +0000549
wdenkb00ec162003-06-19 23:40:20 +0000550 switch (ep->bdtype) {
wdenkaffae2b2002-08-17 09:36:01 +0000551
wdenkb00ec162003-06-19 23:40:20 +0000552 case HYMOD_BDTYPE_IO:
553 case HYMOD_BDTYPE_CLP:
554 case HYMOD_BDTYPE_DSP:
555 printf (" Motorola %s CPU, speeds: %s/%s/%s",
556 cputyp_vals[ep->mpc.type], clk_vals[ep->mpc.cpuspd],
557 clk_vals[ep->mpc.cpmspd], clk_vals[ep->mpc.busspd]);
wdenkaffae2b2002-08-17 09:36:01 +0000558
wdenkb00ec162003-06-19 23:40:20 +0000559 print_mem ("SDRAM", ", ", ep->nsdram, ep->sdramsz);
wdenkaffae2b2002-08-17 09:36:01 +0000560
wdenkb00ec162003-06-19 23:40:20 +0000561 print_mem ("FLASH", ", ", ep->nflash, ep->flashsz);
wdenkaffae2b2002-08-17 09:36:01 +0000562
wdenkb00ec162003-06-19 23:40:20 +0000563 puts ("\n");
wdenkaffae2b2002-08-17 09:36:01 +0000564
wdenkb00ec162003-06-19 23:40:20 +0000565 print_mem ("ZBT", " ", ep->nzbt, ep->zbtsz);
wdenkaffae2b2002-08-17 09:36:01 +0000566
wdenkb00ec162003-06-19 23:40:20 +0000567 if (ep->nxlx > 0) {
568 hymod_xlx_t *xp;
wdenkaffae2b2002-08-17 09:36:01 +0000569
wdenkb00ec162003-06-19 23:40:20 +0000570 if (ep->nxlx == 1) {
571 xp = &ep->xlx[0];
572 printf (", Xilinx %s FPGA (%s/%s/%s)",
573 xlxtyp_vals[xp->type],
574 xlxspd_vals[xp->speed],
575 xlxtmp_vals[xp->temp],
576 xlxgrd_vals[xp->grade]);
577 }
578 else {
579 printf (", %d Xilinx FPGAs (", ep->nxlx);
580 for (i = 0; i < ep->nxlx; i++) {
581 xp = &ep->xlx[i];
582 printf ("%s[%s/%s/%s]%s",
583 xlxtyp_vals[xp->type],
584 xlxspd_vals[xp->speed],
585 xlxtmp_vals[xp->temp],
586 xlxgrd_vals[xp->grade],
587 (i == ep->nxlx - 1) ? ")" : ", ");
588 }
589 }
wdenkaffae2b2002-08-17 09:36:01 +0000590 }
wdenkb00ec162003-06-19 23:40:20 +0000591 else
592 puts(", NO FPGAs");
593
594 puts ("\n");
595
596 if (ep->hss.type > 0)
597 printf (" High Speed Serial: "
598 "%s, %d input%s, %d output%s\n",
599 hstype_vals[ep->hss.type],
600 ep->hss.nchin,
601 (ep->hss.nchin == 1 ? "" : "s"),
602 ep->hss.nchout,
603 (ep->hss.nchout == 1 ? "" : "s"));
604 break;
605
606 case HYMOD_BDTYPE_INPUT:
607 case HYMOD_BDTYPE_ALTINPUT:
608 case HYMOD_BDTYPE_DISPLAY:
609 break;
610
611 default:
612 /* crap! */
613 printf (" UNKNOWN BOARD TYPE: %d\n", ep->bdtype);
614 break;
wdenkaffae2b2002-08-17 09:36:01 +0000615 }
wdenkb00ec162003-06-19 23:40:20 +0000616}
wdenkaffae2b2002-08-17 09:36:01 +0000617
wdenkb00ec162003-06-19 23:40:20 +0000618int
619hymod_eeprom_read (int which, hymod_eeprom_t *ep)
620{
621 char *label = which ? "mezzanine" : "main";
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200622 unsigned dev_addr = CONFIG_SYS_I2C_EEPROM_ADDR | \
wdenkb00ec162003-06-19 23:40:20 +0000623 (which ? HYMOD_EEOFF_MEZZ : HYMOD_EEOFF_MAIN);
624 char filename[50], prompt[50], *dir;
625 int serno, count = 0, rc;
wdenkaffae2b2002-08-17 09:36:01 +0000626
wdenkb00ec162003-06-19 23:40:20 +0000627 rc = eeprom_probe (dev_addr, 0);
wdenkaffae2b2002-08-17 09:36:01 +0000628
wdenkb00ec162003-06-19 23:40:20 +0000629 if (rc > 0) {
630 printf ("*** probe for eeprom failed with code %d\n", rc);
631 return (0);
632 }
633
634 if (rc < 0)
635 return (rc);
636
637 sprintf (prompt, "Enter %s board serial number: ", label);
wdenkaffae2b2002-08-17 09:36:01 +0000638
wdenkb00ec162003-06-19 23:40:20 +0000639 if ((dir = getenv ("bddb_cfgdir")) == NULL)
640 dir = def_bddb_cfgdir;
641
642 for (;;) {
643 int rc;
644
645 if (hymod_eeprom_load (which, ep))
646 return (1);
647
648 printf ("*** %s board EEPROM contents are %sinvalid\n",
649 label, count == 0 ? "" : "STILL ");
650
651 puts ("*** will fetch from server (Ctrl-C to abort)\n");
652
653 serno = hymod_get_serno (prompt);
654
655 if (serno < 0) {
656 if (serno == -1)
657 puts ("\n*** interrupted!");
658 else
659 puts ("\n*** timeout!");
660 puts (" - ignoring eeprom contents\n");
661 return (0);
662 }
663
664 sprintf (filename, "%s/%010d.cfg", dir, serno);
665
666 printf ("*** fetching %s board EEPROM contents from server\n",
667 label);
668
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200669 rc = hymod_eeprom_fetch (which, filename, CONFIG_SYS_LOAD_ADDR);
wdenkb00ec162003-06-19 23:40:20 +0000670
671 if (rc == 0) {
672 puts ("*** fetch failed - ignoring eeprom contents\n");
673 return (0);
674 }
675
676 count++;
677 }
wdenkaffae2b2002-08-17 09:36:01 +0000678}