]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/keymile/common/common.c
km/common: remove saveenv from do_checkboardidhwkey
[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         setenv((char *)"ethaddr", (char *)valbuf);
282
283         /* IVM_MacCount */
284         count = (buf[10] << 24) +
285                    (buf[11] << 16) +
286                    (buf[12] << 8)  +
287                     buf[13];
288         if (count == 0xffffffff)
289                 count = 1;
290         sprintf((char *)valbuf, "%lx", count);
291         ivm_set_value("IVM_MacCount", (char *)valbuf);
292         return 0;
293 }
294
295 int ivm_analyze_eeprom(unsigned char *buf, int len)
296 {
297         unsigned short  val;
298         unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
299         unsigned char   *tmp;
300
301         if (ivm_check_crc(buf, 0) != 0)
302                 return -1;
303
304         ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
305                         "IVM_BoardId", 0, 1);
306         val = ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
307                         "IVM_HWKey", 6, 1);
308         if (val != 0xffff) {
309                 sprintf((char *)valbuf, "%x", ((val / 100) % 10));
310                 ivm_set_value("IVM_HWVariant", (char *)valbuf);
311                 sprintf((char *)valbuf, "%x", (val % 100));
312                 ivm_set_value("IVM_HWVersion", (char *)valbuf);
313         }
314         ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
315                 "IVM_Functions", 12, 0);
316
317         GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8)
318         GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64)
319         tmp = (unsigned char *) getenv("IVM_DeviceName");
320         if (tmp) {
321                 int     len = strlen((char *)tmp);
322                 int     i = 0;
323
324                 while (i < len) {
325                         if (tmp[i] == ';') {
326                                 ivm_set_value("IVM_ShortText",
327                                         (char *)&tmp[i + 1]);
328                                 break;
329                         }
330                         i++;
331                 }
332                 if (i >= len)
333                         ivm_set_value("IVM_ShortText", NULL);
334         } else {
335                 ivm_set_value("IVM_ShortText", NULL);
336         }
337         GET_STRING("IVM_ManufacturerID", IVM_POS_MANU_ID, 32)
338         GET_STRING("IVM_ManufacturerSerialNumber", IVM_POS_MANU_SERIAL, 20)
339         GET_STRING("IVM_ManufacturerPartNumber", IVM_POS_PART_NUMBER, 32)
340         GET_STRING("IVM_ManufacturerBuildState", IVM_POS_BUILD_STATE, 32)
341         GET_STRING("IVM_SupplierPartNumber", IVM_POS_SUPPLIER_PART_NUMBER, 32)
342         GET_STRING("IVM_DelieveryDate", IVM_POS_DELIVERY_DATE, 32)
343         GET_STRING("IVM_SupplierBuildState", IVM_POS_SUPPLIER_BUILD_STATE, 32)
344         GET_STRING("IVM_CustomerID", IVM_POS_CUSTOMER_ID, 32)
345         GET_STRING("IVM_CustomerProductID", IVM_POS_CUSTOMER_PROD_ID, 32)
346
347         if (ivm_check_crc(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0)
348                 return 0;
349         ivm_analyze_block2(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2],
350                 CONFIG_SYS_IVM_EEPROM_PAGE_LEN);
351
352         return 0;
353 }
354
355 int ivm_read_eeprom(void)
356 {
357 #if defined(CONFIG_I2C_MUX)
358         I2C_MUX_DEVICE *dev = NULL;
359 #endif
360         uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
361         uchar   *buf;
362         unsigned dev_addr = CONFIG_SYS_IVM_EEPROM_ADR;
363         int ret;
364
365 #if defined(CONFIG_I2C_MUX)
366         /* First init the Bus, select the Bus */
367 #if defined(CONFIG_SYS_I2C_IVM_BUS)
368         dev = i2c_mux_ident_muxstring((uchar *)CONFIG_SYS_I2C_IVM_BUS);
369 #else
370         buf = (unsigned char *) getenv("EEprom_ivm");
371         if (buf != NULL)
372                 dev = i2c_mux_ident_muxstring(buf);
373 #endif
374         if (dev == NULL) {
375                 printf("Error couldnt add Bus for IVM\n");
376                 return -1;
377         }
378         i2c_set_bus_num(dev->busid);
379 #endif
380
381         buf = (unsigned char *) getenv("EEprom_ivm_addr");
382         if (buf != NULL)
383                 dev_addr = simple_strtoul((char *)buf, NULL, 16);
384
385         /* add deblocking here */
386         i2c_make_abort();
387
388         ret = i2c_read(dev_addr, 0, 1, i2c_buffer,
389                 CONFIG_SYS_IVM_EEPROM_MAX_LEN);
390         if (ret != 0) {
391                 printf ("Error reading EEprom\n");
392                 return -2;
393         }
394
395         return ivm_analyze_eeprom(i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
396 }
397
398 #if defined(CONFIG_SYS_I2C_INIT_BOARD)
399 #define DELAY_ABORT_SEQ         62  /* @200kHz 9 clocks = 44us, 62us is ok */
400 #define DELAY_HALF_PERIOD       (500 / (CONFIG_SYS_I2C_SPEED / 1000))
401
402 #if defined(CONFIG_KM_82XX)
403 #define SDA_MASK        0x00010000
404 #define SCL_MASK        0x00020000
405 void set_pin(int state, unsigned long mask)
406 {
407         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
408
409         if (state)
410                 setbits_be32(&iop->pdat, mask);
411         else
412                 clrbits_be32(&iop->pdat, mask);
413
414         setbits_be32(&iop->pdir, mask);
415 }
416
417 static int get_pin(unsigned long mask)
418 {
419         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
420
421         clrbits_be32(&iop->pdir, mask);
422         return 0 != (in_be32(&iop->pdat) & mask);
423 }
424
425 static void set_sda(int state)
426 {
427         set_pin(state, SDA_MASK);
428 }
429
430 static void set_scl(int state)
431 {
432         set_pin(state, SCL_MASK);
433 }
434
435 static int get_sda(void)
436 {
437         return get_pin(SDA_MASK);
438 }
439
440 static int get_scl(void)
441 {
442         return get_pin(SCL_MASK);
443 }
444
445 #if defined(CONFIG_HARD_I2C)
446 static void setports(int gpio)
447 {
448         ioport_t *iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 3);
449
450         if (gpio) {
451                 clrbits_be32(&iop->ppar, (SDA_MASK | SCL_MASK));
452                 clrbits_be32(&iop->podr, (SDA_MASK | SCL_MASK));
453         } else {
454                 setbits_be32(&iop->ppar, (SDA_MASK | SCL_MASK));
455                 clrbits_be32(&iop->pdir, (SDA_MASK | SCL_MASK));
456                 setbits_be32(&iop->podr, (SDA_MASK | SCL_MASK));
457         }
458 }
459 #endif
460 #endif
461
462 #if !defined(CONFIG_MPC83xx)
463 static void i2c_write_start_seq(void)
464 {
465         set_sda(1);
466         udelay(DELAY_HALF_PERIOD);
467         set_scl(1);
468         udelay(DELAY_HALF_PERIOD);
469         set_sda(0);
470         udelay(DELAY_HALF_PERIOD);
471         set_scl(0);
472         udelay(DELAY_HALF_PERIOD);
473 }
474
475 /*
476  * I2C is a synchronous protocol and resets of the processor in the middle
477  * of an access can block the I2C Bus until a powerdown of the full unit is
478  * done. This function toggles the SCL until the SCL and SCA line are
479  * released, but max. 16 times, after this a I2C start-sequence is sent.
480  * This I2C Deblocking mechanism was developed by Keymile in association
481  * with Anatech and Atmel in 1998.
482  */
483 static int i2c_make_abort(void)
484 {
485
486 #if defined(CONFIG_HARD_I2C) && !defined(MACH_TYPE_KM_KIRKWOOD)
487         immap_t *immap = (immap_t *)CONFIG_SYS_IMMR ;
488         i2c8260_t *i2c  = (i2c8260_t *)&immap->im_i2c;
489
490         /*
491          * disable I2C controller first, otherwhise it thinks we want to
492          * talk to the slave port...
493          */
494         clrbits_8(&i2c->i2c_i2mod, 0x01);
495
496         /* Set the PortPins to GPIO */
497         setports(1);
498 #endif
499
500         int     scl_state = 0;
501         int     sda_state = 0;
502         int     i = 0;
503         int     ret = 0;
504
505         if (!get_sda()) {
506                 ret = -1;
507                 while (i < 16) {
508                         i++;
509                         set_scl(0);
510                         udelay(DELAY_ABORT_SEQ);
511                         set_scl(1);
512                         udelay(DELAY_ABORT_SEQ);
513                         scl_state = get_scl();
514                         sda_state = get_sda();
515                         if (scl_state && sda_state) {
516                                 ret = 0;
517                                 break;
518                         }
519                 }
520         }
521         if (ret == 0)
522                 for (i = 0; i < 5; i++)
523                         i2c_write_start_seq();
524
525         /* respect stop setup time */
526         udelay(DELAY_ABORT_SEQ);
527         set_scl(1);
528         udelay(DELAY_ABORT_SEQ);
529         set_sda(1);
530         get_sda();
531
532 #if defined(CONFIG_HARD_I2C)
533         /* Set the PortPins back to use for I2C */
534         setports(0);
535 #endif
536         return ret;
537 }
538 #endif
539
540 #if defined(CONFIG_MPC83xx)
541 static void i2c_write_start_seq(void)
542 {
543         struct fsl_i2c *dev;
544         dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET);
545         udelay(DELAY_ABORT_SEQ);
546         out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA));
547         udelay(DELAY_ABORT_SEQ);
548         out_8(&dev->cr, (I2C_CR_MEN));
549 }
550
551 static int i2c_make_abort(void)
552 {
553         struct fsl_i2c *dev;
554         dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET);
555         uchar   dummy;
556         uchar   last;
557         int     nbr_read = 0;
558         int     i = 0;
559         int         ret = 0;
560
561         /* wait after each operation to finsh with a delay */
562         out_8(&dev->cr, (I2C_CR_MSTA));
563         udelay(DELAY_ABORT_SEQ);
564         out_8(&dev->cr, (I2C_CR_MEN | I2C_CR_MSTA));
565         udelay(DELAY_ABORT_SEQ);
566         dummy = in_8(&dev->dr);
567         udelay(DELAY_ABORT_SEQ);
568         last = in_8(&dev->dr);
569         nbr_read++;
570
571         /*
572          * do read until the last bit is 1, but stop if the full eeprom is
573          * read.
574          */
575         while (((last & 0x01) != 0x01) &&
576                 (nbr_read < CONFIG_SYS_IVM_EEPROM_MAX_LEN)) {
577                 udelay(DELAY_ABORT_SEQ);
578                 last = in_8(&dev->dr);
579                 nbr_read++;
580         }
581         if ((last & 0x01) != 0x01)
582                 ret = -2;
583         if ((last != 0xff) || (nbr_read > 1))
584                 printf("[INFO] i2c abort after %d bytes (0x%02x)\n",
585                         nbr_read, last);
586         udelay(DELAY_ABORT_SEQ);
587         out_8(&dev->cr, (I2C_CR_MEN));
588         udelay(DELAY_ABORT_SEQ);
589         /* clear status reg */
590         out_8(&dev->sr, 0);
591
592         for (i = 0; i < 5; i++)
593                 i2c_write_start_seq();
594         if (ret != 0)
595                 printf("[ERROR] i2c abort failed after %d bytes (0x%02x)\n",
596                         nbr_read, last);
597
598         return ret;
599 }
600 #endif
601
602 /**
603  * i2c_init_board - reset i2c bus. When the board is powercycled during a
604  * bus transfer it might hang; for details see doc/I2C_Edge_Conditions.
605  */
606 void i2c_init_board(void)
607 {
608         /* Now run the AbortSequence() */
609         i2c_make_abort();
610 }
611 #endif
612 #endif
613
614 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
615 int fdt_set_node_and_value(void *blob,
616                                 char *nodename,
617                                 char *regname,
618                                 void *var,
619                                 int size)
620 {
621         int ret = 0;
622         int nodeoffset = 0;
623
624         nodeoffset = fdt_path_offset(blob, nodename);
625         if (nodeoffset >= 0) {
626                 ret = fdt_setprop(blob, nodeoffset, regname, var,
627                                         size);
628                 if (ret < 0)
629                         printf("ft_blob_update(): cannot set %s/%s "
630                                 "property err:%s\n", nodename, regname,
631                                 fdt_strerror(ret));
632         } else {
633                 printf("ft_blob_update(): cannot find %s node "
634                         "err:%s\n", nodename, fdt_strerror(nodeoffset));
635         }
636         return ret;
637 }
638
639 int fdt_get_node_and_value(void *blob,
640                                 char *nodename,
641                                 char *propname,
642                                 void **var)
643 {
644         int len;
645         int nodeoffset = 0;
646
647         nodeoffset = fdt_path_offset(blob, nodename);
648         if (nodeoffset >= 0) {
649                 *var = (void *)fdt_getprop(blob, nodeoffset, propname, &len);
650                 if (len == 0) {
651                         /* no value */
652                         printf("%s no value\n", __func__);
653                         return -1;
654                 } else if (len > 0) {
655                         return len;
656                 } else {
657                         printf("libfdt fdt_getprop(): %s\n",
658                                 fdt_strerror(len));
659                         return -2;
660                 }
661         } else {
662                 printf("%s: cannot find %s node err:%s\n", __func__,
663                         nodename, fdt_strerror(nodeoffset));
664                 return -3;
665         }
666 }
667 #endif
668
669 #if !defined(MACH_TYPE_KM_KIRKWOOD)
670 int ethernet_present(void)
671 {
672         struct km_bec_fpga *base =
673                 (struct km_bec_fpga *)CONFIG_SYS_KMBEC_FPGA_BASE;
674
675         return in_8(&base->bprth) & PIGGY_PRESENT;
676 }
677 #endif
678
679 int board_eth_init(bd_t *bis)
680 {
681         if (ethernet_present())
682                 return cpu_eth_init(bis);
683
684         return -1;
685 }
686
687 /*
688  * do_setboardid command
689  * read out the board id and the hw key from the intventory EEPROM and set
690  * this values as environment variables.
691  */
692 static int do_setboardid(cmd_tbl_t *cmdtp, int flag, int argc,
693                                 char *const argv[])
694 {
695         unsigned char buf[32];
696         char *p;
697
698         p = get_local_var("IVM_BoardId");
699         if (p == NULL) {
700                 printf("can't get the IVM_Boardid\n");
701                 return 1;
702         }
703         sprintf((char *)buf, "%s", p);
704         setenv("boardid", (char *)buf);
705
706         p = get_local_var("IVM_HWKey");
707         if (p == NULL) {
708                 printf("can't get the IVM_HWKey\n");
709                 return 1;
710         }
711         sprintf((char *)buf, "%s", p);
712         setenv("hwkey", (char *)buf);
713
714         return 0;
715 }
716
717 U_BOOT_CMD(km_setboardid, 1, 0, do_setboardid, "setboardid", "read out bid and "
718                                  "hwkey from IVM and set in environment");
719
720 /*
721  * command km_checkbidhwk
722  *      if "boardid" and "hwkey" are not already set in the environment, do:
723  *              if a "boardIdListHex" exists in the environment:
724  *                      - read ivm data for boardid and hwkey
725  *                      - compare each entry of the boardIdListHex with the
726  *                              IVM data:
727  *                      if match:
728  *                              set environment variables boardid, boardId,
729  *                              hwkey, hwKey to the found values
730  *                              both (boardid and boardId) are set because
731  *                              they might be used differently in the
732  *                              application and in the init scripts (?)
733  *      return 0 in case of match, 1 if not match or error
734  */
735 int do_checkboardidhwk(cmd_tbl_t *cmdtp, int flag, int argc,
736                         char *const argv[])
737 {
738         unsigned long ivmbid = 0, ivmhwkey = 0;
739         unsigned long envbid = 0, envhwkey = 0;
740         char *p;
741         int verbose = argc > 1 && *argv[1] == 'v';
742         int rc = 0;
743
744         /*
745          * first read out the real inventory values, these values are
746          * already stored in the local hush variables
747          */
748         p = get_local_var("IVM_BoardId");
749         if (p == NULL) {
750                 printf("can't get the IVM_Boardid\n");
751                 return 1;
752         }
753         rc = strict_strtoul(p, 16, &ivmbid);
754
755         p = get_local_var("IVM_HWKey");
756         if (p == NULL) {
757                 printf("can't get the IVM_HWKey\n");
758                 return 1;
759         }
760         rc = strict_strtoul(p, 16, &ivmhwkey);
761
762         if (!ivmbid || !ivmhwkey) {
763                 printf("Error: IVM_BoardId and/or IVM_HWKey not set!\n");
764                 return rc;
765         }
766
767         /* now try to read values from environment if available */
768         p = getenv("boardid");
769         if (p != NULL)
770                 rc = strict_strtoul(p, 16, &envbid);
771         p = getenv("hwkey");
772         if (p != NULL)
773                 rc = strict_strtoul(p, 16, &envhwkey);
774
775         if (rc != 0) {
776                 printf("strict_strtoul returns error: %d", rc);
777                 return rc;
778         }
779
780         if (!envbid || !envhwkey) {
781                 /*
782                  * BoardId/HWkey not available in the environment, so try the
783                  * environment variable for BoardId/HWkey list
784                  */
785                 char *bidhwklist = getenv("boardIdListHex");
786
787                 if (bidhwklist) {
788                         int found = 0;
789                         char *rest = bidhwklist;
790                         char *endp;
791
792                         if (verbose) {
793                                 printf("IVM_BoardId: %ld, IVM_HWKey=%ld\n",
794                                         ivmbid, ivmhwkey);
795                                 printf("boardIdHwKeyList: %s\n",
796                                         bidhwklist);
797                         }
798                         while (!found) {
799                                 /* loop over each bid/hwkey pair in the list */
800                                 unsigned long bid   = 0;
801                                 unsigned long hwkey = 0;
802
803                                 while (*rest && !isxdigit(*rest))
804                                         rest++;
805                                 /*
806                                  * use simple_strtoul because we need &end and
807                                  * we know we got non numeric char at the end
808                                  */
809                                 bid = simple_strtoul(rest, &endp, 16);
810                                 /* BoardId and HWkey are separated with a "_" */
811                                 if (*endp == '_') {
812                                         rest  = endp + 1;
813                                         /*
814                                          * use simple_strtoul because we need
815                                          * &end
816                                          */
817                                         hwkey = simple_strtoul(rest, &endp, 16);
818                                         rest  = endp;
819                                         while (*rest && !isxdigit(*rest))
820                                                 rest++;
821                                 }
822                                 if ((!bid) || (!hwkey)) {
823                                         /* end of list */
824                                         break;
825                                 }
826                                 if (verbose) {
827                                         printf("trying bid=0x%lX, hwkey=%ld\n",
828                                                 bid, hwkey);
829                                 }
830                                 /*
831                                  * Compare the values of the found entry in the
832                                  * list with the valid values which are stored
833                                  * in the inventory eeprom. If they are equal
834                                  * set the values in environment variables.
835                                  */
836                                 if ((bid == ivmbid) && (hwkey == ivmhwkey)) {
837                                         char buf[10];
838
839                                         found = 1;
840                                         envbid   = bid;
841                                         envhwkey = hwkey;
842                                         sprintf(buf, "%lx", bid);
843                                         setenv("boardid", buf);
844                                         sprintf(buf, "%lx", hwkey);
845                                         setenv("hwkey", buf);
846                                 }
847                         } /* end while( ! found ) */
848                 }
849         }
850
851         /* compare now the values */
852         if ((ivmbid == envbid) && (ivmhwkey == envhwkey)) {
853                 printf("boardid=0x%3lX, hwkey=%ld\n", envbid, envhwkey);
854                 rc = 0; /* match */
855         } else {
856                 printf("Error: env bId=0x%3lX, hwKey=%ld\n", envbid, envhwkey);
857                 printf("       IVM bId=0x%3lX, hwKey=%ld\n", ivmbid, ivmhwkey);
858                 rc = 1; /* don't match */
859         }
860         return rc;
861 }
862
863 U_BOOT_CMD(km_checkbidhwk, 2, 0, do_checkboardidhwk,
864                 "check boardid and hwkey",
865                 "[v]\n  - check environment parameter "\
866                 "\"boardIdListHex\" against stored boardid and hwkey "\
867                 "from the IVM\n    v: verbose output"
868 );