]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/keymile/common/common.c
Merge branch 'master' of git://git.denx.de/u-boot-mpc85xx
[karo-tx-uboot.git] / board / keymile / common / common.c
1 /*
2  * (C) Copyright 2008
3  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
4  *
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 #if defined(CONFIG_KM82XX)
26 #include <mpc8260.h>
27 #endif
28 #include <ioports.h>
29 #include <command.h>
30 #include <malloc.h>
31 #include <hush.h>
32 #include <net.h>
33 #include <netdev.h>
34 #include <asm/io.h>
35 #include <linux/ctype.h>
36
37 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
38 #include <libfdt.h>
39 #endif
40
41 #include "../common/common.h"
42 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
43 #include <i2c.h>
44
45 static void i2c_write_start_seq(void);
46 static int i2c_make_abort(void);
47 DECLARE_GLOBAL_DATA_PTR;
48
49 int ivm_calc_crc(unsigned char *buf, int len)
50 {
51         const unsigned short crc_tab[16] = {
52                 0x0000, 0xCC01, 0xD801, 0x1400,
53                 0xF001, 0x3C00, 0x2800, 0xE401,
54                 0xA001, 0x6C00, 0x7800, 0xB401,
55                 0x5000, 0x9C01, 0x8801, 0x4400};
56
57         unsigned short crc     = 0;   /* final result */
58         unsigned short r1      = 0;   /* temp */
59         unsigned char  byte    = 0;   /* input buffer */
60         int     i;
61
62         /* calculate CRC from array data */
63         for (i = 0; i < len; i++) {
64                 byte = buf[i];
65
66                 /* lower 4 bits */
67                 r1 = crc_tab[crc & 0xF];
68                 crc = ((crc) >> 4) & 0x0FFF;
69                 crc = crc ^ r1 ^ crc_tab[byte & 0xF];
70
71                 /* upper 4 bits */
72                 r1 = crc_tab[crc & 0xF];
73                 crc = (crc >> 4) & 0x0FFF;
74                 crc = crc ^ r1 ^ crc_tab[(byte >> 4) & 0xF];
75         }
76         return crc;
77 }
78
79 /*
80  * Set Keymile specific environment variables
81  * Currently only some memory layout variables are calculated here
82  * ... ------------------------------------------------
83  * ... |@rootfsaddr |@pnvramaddr |@varaddr |@reserved |@END_OF_RAM
84  * ... |<------------------- pram ------------------->|
85  * ... ------------------------------------------------
86  * @END_OF_RAM: denotes the RAM size
87  * @pnvramaddr: Startadress of pseudo non volatile RAM in hex
88  * @pram      : preserved ram size in k
89  * @varaddr   : startadress for /var mounted into RAM
90  */
91 int set_km_env(void)
92 {
93         uchar buf[32];
94         unsigned int pnvramaddr;
95         unsigned int pram;
96         unsigned int varaddr;
97
98         pnvramaddr = gd->ram_size - CONFIG_KM_RESERVED_PRAM - CONFIG_KM_PHRAM
99                         - CONFIG_KM_PNVRAM;
100         sprintf((char *)buf, "0x%x", pnvramaddr);
101         setenv("pnvramaddr", (char *)buf);
102
103         pram = (CONFIG_KM_RESERVED_PRAM + CONFIG_KM_PHRAM + CONFIG_KM_PNVRAM) /
104                 0x400;
105         sprintf((char *)buf, "0x%x", pram);
106         setenv("pram", (char *)buf);
107
108         varaddr = gd->ram_size - CONFIG_KM_RESERVED_PRAM - CONFIG_KM_PHRAM;
109         sprintf((char *)buf, "0x%x", varaddr);
110         setenv("varaddr", (char *)buf);
111         return 0;
112 }
113
114 static int ivm_set_value(char *name, char *value)
115 {
116         char tempbuf[256];
117
118         if (value != NULL) {
119                 sprintf(tempbuf, "%s=%s", name, value);
120                 return set_local_var(tempbuf, 0);
121         } else {
122                 unset_local_var(name);
123         }
124         return 0;
125 }
126
127 static int ivm_get_value(unsigned char *buf, int len, char *name, int off,
128                                 int check)
129 {
130         unsigned short  val;
131         unsigned char   valbuf[30];
132
133         if ((buf[off + 0] != buf[off + 2]) &&
134             (buf[off + 2] != buf[off + 4])) {
135                 printf("%s Error corrupted %s\n", __func__, name);
136                 val = -1;
137         } else {
138                 val = buf[off + 0] + (buf[off + 1] << 8);
139                 if ((val == 0) && (check == 1))
140                         val = -1;
141         }
142         sprintf((char *)valbuf, "%x", val);
143         ivm_set_value(name, (char *)valbuf);
144         return val;
145 }
146
147 #define INV_BLOCKSIZE           0x100
148 #define INV_DATAADDRESS         0x21
149 #define INVENTORYDATASIZE       (INV_BLOCKSIZE - INV_DATAADDRESS - 3)
150
151 #define IVM_POS_SHORT_TEXT              0
152 #define IVM_POS_MANU_ID                 1
153 #define IVM_POS_MANU_SERIAL             2
154 #define IVM_POS_PART_NUMBER             3
155 #define IVM_POS_BUILD_STATE             4
156 #define IVM_POS_SUPPLIER_PART_NUMBER    5
157 #define IVM_POS_DELIVERY_DATE           6
158 #define IVM_POS_SUPPLIER_BUILD_STATE    7
159 #define IVM_POS_CUSTOMER_ID             8
160 #define IVM_POS_CUSTOMER_PROD_ID        9
161 #define IVM_POS_HISTORY                 10
162 #define IVM_POS_SYMBOL_ONLY             11
163
164 static char convert_char(char c)
165 {
166         return (c < ' ' || c > '~') ? '.' : c;
167 }
168
169 static int ivm_findinventorystring(int type,
170                                         unsigned char* const string,
171                                         unsigned long maxlen,
172                                         unsigned char *buf)
173 {
174         int xcode = 0;
175         unsigned long cr = 0;
176         unsigned long addr = INV_DATAADDRESS;
177         unsigned long size = 0;
178         unsigned long nr = type;
179         int stop = 0;   /* stop on semicolon */
180
181         memset(string, '\0', maxlen);
182         switch (type) {
183                 case IVM_POS_SYMBOL_ONLY:
184                         nr = 0;
185                         stop= 1;
186                 break;
187                 default:
188                         nr = type;
189                         stop = 0;
190         }
191
192         /* Look for the requested number of CR. */
193         while ((cr != nr) && (addr < INVENTORYDATASIZE)) {
194                 if ((buf[addr] == '\r')) {
195                         cr++;
196                 }
197                 addr++;
198         }
199
200         /*
201          * the expected number of CR was found until the end of the IVM
202          *  content --> fill string
203          */
204         if (addr < INVENTORYDATASIZE) {
205                 /* Copy the IVM string in the corresponding string */
206                 for (; (buf[addr] != '\r')                      &&
207                         ((buf[addr] != ';') ||  (!stop))        &&
208                         (size < (maxlen - 1)                    &&
209                         (addr < INVENTORYDATASIZE)); addr++)
210                 {
211                         size += sprintf((char *)string + size, "%c",
212                                                 convert_char (buf[addr]));
213                 }
214
215                 /*
216                  * copy phase is done: check if everything is ok. If not,
217                  * the inventory data is most probably corrupted: tell
218                  * the world there is a problem!
219                  */
220                 if (addr == INVENTORYDATASIZE) {
221                         xcode = -1;
222                         printf("Error end of string not found\n");
223                 } else if ((size >= (maxlen - 1)) &&
224                            (buf[addr] != '\r')) {
225                         xcode = -1;
226                         printf("string too long till next CR\n");
227                 }
228         } else {
229                 /*
230                  * some CR are missing...
231                  * the inventory data is most probably corrupted
232                  */
233                 xcode = -1;
234                 printf("not enough cr found\n");
235         }
236         return xcode;
237 }
238
239 #define GET_STRING(name, which, len) \
240         if (ivm_findinventorystring(which, valbuf, len, buf) == 0) { \
241                 ivm_set_value(name, (char *)valbuf); \
242         }
243
244 static int ivm_check_crc(unsigned char *buf, int block)
245 {
246         unsigned long   crc;
247         unsigned long   crceeprom;
248
249         crc = ivm_calc_crc(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2);
250         crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \
251                         buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256);
252         if (crc != crceeprom) {
253                 if (block == 0)
254                         printf("Error CRC Block: %d EEprom: calculated: \
255                         %lx EEprom: %lx\n", block, crc, crceeprom);
256                 return -1;
257         }
258         return 0;
259 }
260
261 static int ivm_analyze_block2(unsigned char *buf, int len)
262 {
263         unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
264         unsigned long   count;
265
266         /* IVM_MacAddress */
267         sprintf((char *)valbuf, "%pM", buf);
268         ivm_set_value("IVM_MacAddress", (char *)valbuf);
269         /* if an offset is defined, add it */
270 #if defined(CONFIG_PIGGY_MAC_ADRESS_OFFSET)
271         if (CONFIG_PIGGY_MAC_ADRESS_OFFSET > 0) {
272                 unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6];
273
274                 val += CONFIG_PIGGY_MAC_ADRESS_OFFSET;
275                 buf[4] = (val >> 16) & 0xff;
276                 buf[5] = (val >> 8) & 0xff;
277                 buf[6] = val & 0xff;
278                 sprintf((char *)valbuf, "%pM", buf);
279         }
280 #endif
281         if (getenv("ethaddr") == NULL)
282                 setenv((char *)"ethaddr", (char *)valbuf);
283
284         /* IVM_MacCount */
285         count = (buf[10] << 24) +
286                    (buf[11] << 16) +
287                    (buf[12] << 8)  +
288                     buf[13];
289         if (count == 0xffffffff)
290                 count = 1;
291         sprintf((char *)valbuf, "%lx", count);
292         ivm_set_value("IVM_MacCount", (char *)valbuf);
293         return 0;
294 }
295
296 int ivm_analyze_eeprom(unsigned char *buf, int len)
297 {
298         unsigned short  val;
299         unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
300         unsigned char   *tmp;
301
302         if (ivm_check_crc(buf, 0) != 0)
303                 return -1;
304
305         ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
306                         "IVM_BoardId", 0, 1);
307         val = ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
308                         "IVM_HWKey", 6, 1);
309         if (val != 0xffff) {
310                 sprintf((char *)valbuf, "%x", ((val / 100) % 10));
311                 ivm_set_value("IVM_HWVariant", (char *)valbuf);
312                 sprintf((char *)valbuf, "%x", (val % 100));
313                 ivm_set_value("IVM_HWVersion", (char *)valbuf);
314         }
315         ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
316                 "IVM_Functions", 12, 0);
317
318         GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8)
319         GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64)
320         tmp = (unsigned char *) getenv("IVM_DeviceName");
321         if (tmp) {
322                 int     len = strlen((char *)tmp);
323                 int     i = 0;
324
325                 while (i < len) {
326                         if (tmp[i] == ';') {
327                                 ivm_set_value("IVM_ShortText",
328                                         (char *)&tmp[i + 1]);
329                                 break;
330                         }
331                         i++;
332                 }
333                 if (i >= len)
334                         ivm_set_value("IVM_ShortText", NULL);
335         } else {
336                 ivm_set_value("IVM_ShortText", NULL);
337         }
338         GET_STRING("IVM_ManufacturerID", IVM_POS_MANU_ID, 32)
339         GET_STRING("IVM_ManufacturerSerialNumber", IVM_POS_MANU_SERIAL, 20)
340         GET_STRING("IVM_ManufacturerPartNumber", IVM_POS_PART_NUMBER, 32)
341         GET_STRING("IVM_ManufacturerBuildState", IVM_POS_BUILD_STATE, 32)
342         GET_STRING("IVM_SupplierPartNumber", IVM_POS_SUPPLIER_PART_NUMBER, 32)
343         GET_STRING("IVM_DelieveryDate", IVM_POS_DELIVERY_DATE, 32)
344         GET_STRING("IVM_SupplierBuildState", IVM_POS_SUPPLIER_BUILD_STATE, 32)
345         GET_STRING("IVM_CustomerID", IVM_POS_CUSTOMER_ID, 32)
346         GET_STRING("IVM_CustomerProductID", IVM_POS_CUSTOMER_PROD_ID, 32)
347
348         if (ivm_check_crc(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0)
349                 return 0;
350         ivm_analyze_block2(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2],
351                 CONFIG_SYS_IVM_EEPROM_PAGE_LEN);
352
353         return 0;
354 }
355
356 int ivm_read_eeprom(void)
357 {
358 #if defined(CONFIG_I2C_MUX)
359         I2C_MUX_DEVICE *dev = NULL;
360 #endif
361         uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
362         uchar   *buf;
363         unsigned dev_addr = CONFIG_SYS_IVM_EEPROM_ADR;
364         int ret;
365
366 #if defined(CONFIG_I2C_MUX)
367         /* First init the Bus, select the Bus */
368 #if defined(CONFIG_SYS_I2C_IVM_BUS)
369         dev = i2c_mux_ident_muxstring((uchar *)CONFIG_SYS_I2C_IVM_BUS);
370 #else
371         buf = (unsigned char *) getenv("EEprom_ivm");
372         if (buf != NULL)
373                 dev = i2c_mux_ident_muxstring(buf);
374 #endif
375         if (dev == NULL) {
376                 printf("Error couldnt add Bus for IVM\n");
377                 return -1;
378         }
379         i2c_set_bus_num(dev->busid);
380 #endif
381
382         buf = (unsigned char *) getenv("EEprom_ivm_addr");
383         if (buf != NULL)
384                 dev_addr = simple_strtoul((char *)buf, NULL, 16);
385
386         /* add deblocking here */
387         i2c_make_abort();
388
389         ret = i2c_read(dev_addr, 0, 1, i2c_buffer,
390                 CONFIG_SYS_IVM_EEPROM_MAX_LEN);
391         if (ret != 0) {
392                 printf ("Error reading EEprom\n");
393                 return -2;
394         }
395
396         return ivm_analyze_eeprom(i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
397 }
398
399 #if defined(CONFIG_SYS_I2C_INIT_BOARD)
400 #define DELAY_ABORT_SEQ         62  /* @200kHz 9 clocks = 44us, 62us is ok */
401 #define DELAY_HALF_PERIOD       (500 / (CONFIG_SYS_I2C_SPEED / 1000))
402
403 #if defined(CONFIG_KM_82XX)
404 #define SDA_MASK        0x00010000
405 #define SCL_MASK        0x00020000
406 void set_pin(int state, unsigned long mask)
407 {
408         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
409
410         if (state)
411                 setbits_be32(&iop->pdat, mask);
412         else
413                 clrbits_be32(&iop->pdat, mask);
414
415         setbits_be32(&iop->pdir, mask);
416 }
417
418 static int get_pin(unsigned long mask)
419 {
420         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
421
422         clrbits_be32(&iop->pdir, mask);
423         return 0 != (in_be32(&iop->pdat) & mask);
424 }
425
426 static void set_sda(int state)
427 {
428         set_pin(state, SDA_MASK);
429 }
430
431 static void set_scl(int state)
432 {
433         set_pin(state, SCL_MASK);
434 }
435
436 static int get_sda(void)
437 {
438         return get_pin(SDA_MASK);
439 }
440
441 static int get_scl(void)
442 {
443         return get_pin(SCL_MASK);
444 }
445
446 #if defined(CONFIG_HARD_I2C)
447 static void setports(int gpio)
448 {
449         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
450
451         if (gpio) {
452                 clrbits_be32(&iop->ppar, (SDA_MASK | SCL_MASK));
453                 clrbits_be32(&iop->podr, (SDA_MASK | SCL_MASK));
454         } else {
455                 setbits_be32(&iop->ppar, (SDA_MASK | SCL_MASK));
456                 clrbits_be32(&iop->pdir, (SDA_MASK | SCL_MASK));
457                 setbits_be32(&iop->podr, (SDA_MASK | SCL_MASK));
458         }
459 }
460 #endif
461 #endif
462
463 #if !defined(CONFIG_MPC83xx)
464 static void i2c_write_start_seq(void)
465 {
466         set_sda(1);
467         udelay(DELAY_HALF_PERIOD);
468         set_scl(1);
469         udelay(DELAY_HALF_PERIOD);
470         set_sda(0);
471         udelay(DELAY_HALF_PERIOD);
472         set_scl(0);
473         udelay(DELAY_HALF_PERIOD);
474 }
475
476 /*
477  * I2C is a synchronous protocol and resets of the processor in the middle
478  * of an access can block the I2C Bus until a powerdown of the full unit is
479  * done. This function toggles the SCL until the SCL and SCA line are
480  * released, but max. 16 times, after this a I2C start-sequence is sent.
481  * This I2C Deblocking mechanism was developed by Keymile in association
482  * with Anatech and Atmel in 1998.
483  */
484 static int i2c_make_abort(void)
485 {
486
487 #if defined(CONFIG_HARD_I2C) && !defined(MACH_TYPE_KM_KIRKWOOD)
488         immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
489         i2c8260_t *i2c  = (i2c8260_t *)&immap->im_i2c;
490
491         /*
492          * disable I2C controller first, otherwhise it thinks we want to
493          * talk to the slave port...
494          */
495         clrbits_8(&i2c->i2c_i2mod, 0x01);
496
497         /* Set the PortPins to GPIO */
498         setports(1);
499 #endif
500
501         int     scl_state = 0;
502         int     sda_state = 0;
503         int     i = 0;
504         int     ret = 0;
505
506         if (!get_sda()) {
507                 ret = -1;
508                 while (i < 16) {
509                         i++;
510                         set_scl(0);
511                         udelay(DELAY_ABORT_SEQ);
512                         set_scl(1);
513                         udelay(DELAY_ABORT_SEQ);
514                         scl_state = get_scl();
515                         sda_state = get_sda();
516                         if (scl_state && sda_state) {
517                                 ret = 0;
518                                 break;
519                         }
520                 }
521         }
522         if (ret == 0)
523                 for (i = 0; i < 5; i++)
524                         i2c_write_start_seq();
525
526         /* respect stop setup time */
527         udelay(DELAY_ABORT_SEQ);
528         set_scl(1);
529         udelay(DELAY_ABORT_SEQ);
530         set_sda(1);
531         get_sda();
532
533 #if defined(CONFIG_HARD_I2C)
534         /* Set the PortPins back to use for I2C */
535         setports(0);
536 #endif
537         return ret;
538 }
539 #endif
540
541 #if defined(CONFIG_MPC83xx)
542 static void i2c_write_start_seq(void)
543 {
544         struct fsl_i2c *dev;
545         dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET);
546         udelay(DELAY_ABORT_SEQ);
547         out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA));
548         udelay(DELAY_ABORT_SEQ);
549         out_8(&dev->cr, (I2C_CR_MEN));
550 }
551
552 static int i2c_make_abort(void)
553 {
554         struct fsl_i2c *dev;
555         dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET);
556         uchar   dummy;
557         uchar   last;
558         int     nbr_read = 0;
559         int     i = 0;
560         int         ret = 0;
561
562         /* wait after each operation to finsh with a delay */
563         out_8(&dev->cr, (I2C_CR_MSTA));
564         udelay(DELAY_ABORT_SEQ);
565         out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA));
566         udelay(DELAY_ABORT_SEQ);
567         dummy = in_8(&dev->dr);
568         udelay(DELAY_ABORT_SEQ);
569         last = in_8(&dev->dr);
570         nbr_read++;
571
572         /*
573          * do read until the last bit is 1, but stop if the full eeprom is
574          * read.
575          */
576         while (((last & 0x01) != 0x01) &&
577                 (nbr_read < CONFIG_SYS_IVM_EEPROM_MAX_LEN)) {
578                 udelay(DELAY_ABORT_SEQ);
579                 last = in_8(&dev->dr);
580                 nbr_read++;
581         }
582         if ((last & 0x01) != 0x01)
583                 ret = -2;
584         if ((last != 0xff) || (nbr_read > 1))
585                 printf("[INFO] i2c abort after %d bytes (0x%02x)\n",
586                         nbr_read, last);
587         udelay(DELAY_ABORT_SEQ);
588         out_8(&dev->cr, (I2C_CR_MEN));
589         udelay(DELAY_ABORT_SEQ);
590         /* clear status reg */
591         out_8(&dev->sr, 0);
592
593         for (i = 0; i < 5; i++)
594                 i2c_write_start_seq();
595         if (ret != 0)
596                 printf("[ERROR] i2c abort failed after %d bytes (0x%02x)\n",
597                         nbr_read, last);
598
599         return ret;
600 }
601 #endif
602
603 /**
604  * i2c_init_board - reset i2c bus. When the board is powercycled during a
605  * bus transfer it might hang; for details see doc/I2C_Edge_Conditions.
606  */
607 void i2c_init_board(void)
608 {
609         /* Now run the AbortSequence() */
610         i2c_make_abort();
611 }
612 #endif
613 #endif
614
615 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
616 int fdt_set_node_and_value(void *blob,
617                                 char *nodename,
618                                 char *regname,
619                                 void *var,
620                                 int size)
621 {
622         int ret = 0;
623         int nodeoffset = 0;
624
625         nodeoffset = fdt_path_offset(blob, nodename);
626         if (nodeoffset >= 0) {
627                 ret = fdt_setprop(blob, nodeoffset, regname, var,
628                                         size);
629                 if (ret < 0)
630                         printf("ft_blob_update(): cannot set %s/%s "
631                                 "property err:%s\n", nodename, regname,
632                                 fdt_strerror(ret));
633         } else {
634                 printf("ft_blob_update(): cannot find %s node "
635                         "err:%s\n", nodename, fdt_strerror(nodeoffset));
636         }
637         return ret;
638 }
639
640 int fdt_get_node_and_value(void *blob,
641                                 char *nodename,
642                                 char *propname,
643                                 void **var)
644 {
645         int len;
646         int nodeoffset = 0;
647
648         nodeoffset = fdt_path_offset(blob, nodename);
649         if (nodeoffset >= 0) {
650                 *var = (void *)fdt_getprop(blob, nodeoffset, propname, &len);
651                 if (len == 0) {
652                         /* no value */
653                         printf("%s no value\n", __func__);
654                         return -1;
655                 } else if (len > 0) {
656                         return len;
657                 } else {
658                         printf("libfdt fdt_getprop(): %s\n",
659                                 fdt_strerror(len));
660                         return -2;
661                 }
662         } else {
663                 printf("%s: cannot find %s node err:%s\n", __func__,
664                         nodename, fdt_strerror(nodeoffset));
665                 return -3;
666         }
667 }
668 #endif
669
670 #if !defined(MACH_TYPE_KM_KIRKWOOD)
671 int ethernet_present(void)
672 {
673         struct km_bec_fpga *base =
674                 (struct km_bec_fpga *)CONFIG_SYS_KMBEC_FPGA_BASE;
675
676         return in_8(&base->bprth) & PIGGY_PRESENT;
677 }
678 #endif
679
680 int board_eth_init(bd_t *bis)
681 {
682         if (ethernet_present())
683                 return cpu_eth_init(bis);
684
685         return -1;
686 }
687
688 /*
689  * do_setboardid command
690  * read out the board id and the hw key from the intventory EEPROM and set
691  * this values as environment variables.
692  */
693 static int do_setboardid(cmd_tbl_t *cmdtp, int flag, int argc,
694                                 char *const argv[])
695 {
696         unsigned char buf[32];
697         char *p;
698
699         p = get_local_var("IVM_BoardId");
700         if (p == NULL) {
701                 printf("can't get the IVM_Boardid\n");
702                 return 1;
703         }
704         sprintf((char *)buf, "%s", p);
705         setenv("boardid", (char *)buf);
706
707         p = get_local_var("IVM_HWKey");
708         if (p == NULL) {
709                 printf("can't get the IVM_HWKey\n");
710                 return 1;
711         }
712         sprintf((char *)buf, "%s", p);
713         setenv("hwkey", (char *)buf);
714
715         return 0;
716 }
717
718 U_BOOT_CMD(km_setboardid, 1, 0, do_setboardid, "setboardid", "read out bid and "
719                                  "hwkey from IVM and set in environment");
720
721 /*
722  * command km_checkbidhwk
723  *      if "boardid" and "hwkey" are not already set in the environment, do:
724  *              if a "boardIdListHex" exists in the environment:
725  *                      - read ivm data for boardid and hwkey
726  *                      - compare each entry of the boardIdListHex with the
727  *                              IVM data:
728  *                      if match:
729  *                              set environment variables boardid, boardId,
730  *                              hwkey, hwKey to the found values
731  *                              both (boardid and boardId) are set because
732  *                              they might be used differently in the
733  *                              application and in the init scripts (?)
734  *      return 0 in case of match, 1 if not match or error
735  */
736 int do_checkboardidhwk(cmd_tbl_t *cmdtp, int flag, int argc,
737                         char *const argv[])
738 {
739         unsigned long ivmbid = 0, ivmhwkey = 0;
740         unsigned long envbid = 0, envhwkey = 0;
741         char *p;
742         int verbose = argc > 1 && *argv[1] == 'v';
743         int rc = 0;
744
745         /*
746          * first read out the real inventory values, these values are
747          * already stored in the local hush variables
748          */
749         p = get_local_var("IVM_BoardId");
750         if (p == NULL) {
751                 printf("can't get the IVM_Boardid\n");
752                 return 1;
753         }
754         rc = strict_strtoul(p, 16, &ivmbid);
755
756         p = get_local_var("IVM_HWKey");
757         if (p == NULL) {
758                 printf("can't get the IVM_HWKey\n");
759                 return 1;
760         }
761         rc = strict_strtoul(p, 16, &ivmhwkey);
762
763         if (!ivmbid || !ivmhwkey) {
764                 printf("Error: IVM_BoardId and/or IVM_HWKey not set!\n");
765                 return rc;
766         }
767
768         /* now try to read values from environment if available */
769         p = getenv("boardid");
770         if (p != NULL)
771                 rc = strict_strtoul(p, 16, &envbid);
772         p = getenv("hwkey");
773         if (p != NULL)
774                 rc = strict_strtoul(p, 16, &envhwkey);
775
776         if (rc != 0) {
777                 printf("strict_strtoul returns error: %d", rc);
778                 return rc;
779         }
780
781         if (!envbid || !envhwkey) {
782                 /*
783                  * BoardId/HWkey not available in the environment, so try the
784                  * environment variable for BoardId/HWkey list
785                  */
786                 char *bidhwklist = getenv("boardIdListHex");
787
788                 if (bidhwklist) {
789                         int found = 0;
790                         char *rest = bidhwklist;
791                         char *endp;
792
793                         if (verbose) {
794                                 printf("IVM_BoardId: %ld, IVM_HWKey=%ld\n",
795                                         ivmbid, ivmhwkey);
796                                 printf("boardIdHwKeyList: %s\n",
797                                         bidhwklist);
798                         }
799                         while (!found) {
800                                 /* loop over each bid/hwkey pair in the list */
801                                 unsigned long bid   = 0;
802                                 unsigned long hwkey = 0;
803
804                                 while (*rest && !isxdigit(*rest))
805                                         rest++;
806                                 /*
807                                  * use simple_strtoul because we need &end and
808                                  * we know we got non numeric char at the end
809                                  */
810                                 bid = simple_strtoul(rest, &endp, 16);
811                                 /* BoardId and HWkey are separated with a "_" */
812                                 if (*endp == '_') {
813                                         rest  = endp + 1;
814                                         /*
815                                          * use simple_strtoul because we need
816                                          * &end
817                                          */
818                                         hwkey = simple_strtoul(rest, &endp, 16);
819                                         rest  = endp;
820                                         while (*rest && !isxdigit(*rest))
821                                                 rest++;
822                                 }
823                                 if ((!bid) || (!hwkey)) {
824                                         /* end of list */
825                                         break;
826                                 }
827                                 if (verbose) {
828                                         printf("trying bid=0x%lX, hwkey=%ld\n",
829                                                 bid, hwkey);
830                                 }
831                                 /*
832                                  * Compare the values of the found entry in the
833                                  * list with the valid values which are stored
834                                  * in the inventory eeprom. If they are equal
835                                  * store the values in environment variables
836                                  * and save the environment.
837                                  * This can only happen once for the lifetime
838                                  * of a board, because once saved the function
839                                  * will never reach the while loop.
840                                  */
841                                 if ((bid == ivmbid) && (hwkey == ivmhwkey)) {
842                                         char buf[10];
843
844                                         found = 1;
845                                         envbid   = bid;
846                                         envhwkey = hwkey;
847                                         sprintf(buf, "%lx", bid);
848                                         setenv("boardid", buf);
849                                         sprintf(buf, "%lx", hwkey);
850                                         setenv("hwkey", buf);
851                                         saveenv();
852                                 }
853                         } /* end while( ! found ) */
854                 }
855         }
856
857         /* compare now the values */
858         if ((ivmbid == envbid) && (ivmhwkey == envhwkey)) {
859                 printf("boardid=0x%3lX, hwkey=%ld\n", envbid, envhwkey);
860                 rc = 0; /* match */
861         } else {
862                 printf("Error: env bId=0x%3lX, hwKey=%ld\n", envbid, envhwkey);
863                 printf("       IVM bId=0x%3lX, hwKey=%ld\n", ivmbid, ivmhwkey);
864                 rc = 1; /* don't match */
865         }
866         return rc;
867 }
868
869 U_BOOT_CMD(km_checkbidhwk, 2, 0, do_checkboardidhwk,
870                 "check boardid and hwkey",
871                 "[v]\n  - check environment parameter "\
872                 "\"boardIdListHex\" against stored boardid and hwkey "\
873                 "from the IVM\n    v: verbose output"
874 );