]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/keymile/common/common.c
9adfefaf6aac9c89cfec7e86429da150aabace33
[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
36 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_OF_LIBFDT)
37 #include <libfdt.h>
38 #endif
39
40 #include "../common/common.h"
41 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
42 #include <i2c.h>
43
44 static void i2c_write_start_seq(void);
45 static int i2c_make_abort(void);
46 DECLARE_GLOBAL_DATA_PTR;
47
48 int ivm_calc_crc(unsigned char *buf, int len)
49 {
50         const unsigned short crc_tab[16] = {
51                 0x0000, 0xCC01, 0xD801, 0x1400,
52                 0xF001, 0x3C00, 0x2800, 0xE401,
53                 0xA001, 0x6C00, 0x7800, 0xB401,
54                 0x5000, 0x9C01, 0x8801, 0x4400};
55
56         unsigned short crc     = 0;   /* final result */
57         unsigned short r1      = 0;   /* temp */
58         unsigned char  byte    = 0;   /* input buffer */
59         int     i;
60
61         /* calculate CRC from array data */
62         for (i = 0; i < len; i++) {
63                 byte = buf[i];
64
65                 /* lower 4 bits */
66                 r1 = crc_tab[crc & 0xF];
67                 crc = ((crc) >> 4) & 0x0FFF;
68                 crc = crc ^ r1 ^ crc_tab[byte & 0xF];
69
70                 /* upper 4 bits */
71                 r1 = crc_tab[crc & 0xF];
72                 crc = (crc >> 4) & 0x0FFF;
73                 crc = crc ^ r1 ^ crc_tab[(byte >> 4) & 0xF];
74         }
75         return crc;
76 }
77
78 /*
79  * Set Keymile specific environment variables
80  * Currently only some memory layout variables are calculated here
81  * ... ------------------------------------------------
82  * ... |@rootfsaddr |@pnvramaddr |@varaddr |@reserved |@END_OF_RAM
83  * ... |<------------------- pram ------------------->|
84  * ... ------------------------------------------------
85  * @END_OF_RAM: denotes the RAM size
86  * @pnvramaddr: Startadress of pseudo non volatile RAM in hex
87  * @pram      : preserved ram size in k
88  * @varaddr   : startadress for /var mounted into RAM
89  */
90 int set_km_env(void)
91 {
92         uchar buf[32];
93         unsigned int pnvramaddr;
94         unsigned int pram;
95         unsigned int varaddr;
96
97         pnvramaddr = gd->ram_size - CONFIG_KM_RESERVED_PRAM - CONFIG_KM_PHRAM
98                         - CONFIG_KM_PNVRAM;
99         sprintf((char *)buf, "0x%x", pnvramaddr);
100         setenv("pnvramaddr", (char *)buf);
101
102         pram = (CONFIG_KM_RESERVED_PRAM + CONFIG_KM_PHRAM + CONFIG_KM_PNVRAM) /
103                 0x400;
104         sprintf((char *)buf, "0x%x", pram);
105         setenv("pram", (char *)buf);
106
107         varaddr = gd->ram_size - CONFIG_KM_RESERVED_PRAM - CONFIG_KM_PHRAM;
108         sprintf((char *)buf, "0x%x", varaddr);
109         setenv("varaddr", (char *)buf);
110         return 0;
111 }
112
113 static int ivm_set_value(char *name, char *value)
114 {
115         char tempbuf[256];
116
117         if (value != NULL) {
118                 sprintf(tempbuf, "%s=%s", name, value);
119                 return set_local_var(tempbuf, 0);
120         } else {
121                 unset_local_var(name);
122         }
123         return 0;
124 }
125
126 static int ivm_get_value(unsigned char *buf, int len, char *name, int off,
127                                 int check)
128 {
129         unsigned short  val;
130         unsigned char   valbuf[30];
131
132         if ((buf[off + 0] != buf[off + 2]) &&
133             (buf[off + 2] != buf[off + 4])) {
134                 printf("%s Error corrupted %s\n", __func__, name);
135                 val = -1;
136         } else {
137                 val = buf[off + 0] + (buf[off + 1] << 8);
138                 if ((val == 0) && (check == 1))
139                         val = -1;
140         }
141         sprintf((char *)valbuf, "%x", val);
142         ivm_set_value(name, (char *)valbuf);
143         return val;
144 }
145
146 #define INV_BLOCKSIZE           0x100
147 #define INV_DATAADDRESS         0x21
148 #define INVENTORYDATASIZE       (INV_BLOCKSIZE - INV_DATAADDRESS - 3)
149
150 #define IVM_POS_SHORT_TEXT              0
151 #define IVM_POS_MANU_ID                 1
152 #define IVM_POS_MANU_SERIAL             2
153 #define IVM_POS_PART_NUMBER             3
154 #define IVM_POS_BUILD_STATE             4
155 #define IVM_POS_SUPPLIER_PART_NUMBER    5
156 #define IVM_POS_DELIVERY_DATE           6
157 #define IVM_POS_SUPPLIER_BUILD_STATE    7
158 #define IVM_POS_CUSTOMER_ID             8
159 #define IVM_POS_CUSTOMER_PROD_ID        9
160 #define IVM_POS_HISTORY                 10
161 #define IVM_POS_SYMBOL_ONLY             11
162
163 static char convert_char(char c)
164 {
165         return (c < ' ' || c > '~') ? '.' : c;
166 }
167
168 static int ivm_findinventorystring(int type,
169                                         unsigned char* const string,
170                                         unsigned long maxlen,
171                                         unsigned char *buf)
172 {
173         int xcode = 0;
174         unsigned long cr = 0;
175         unsigned long addr = INV_DATAADDRESS;
176         unsigned long size = 0;
177         unsigned long nr = type;
178         int stop = 0;   /* stop on semicolon */
179
180         memset(string, '\0', maxlen);
181         switch (type) {
182                 case IVM_POS_SYMBOL_ONLY:
183                         nr = 0;
184                         stop= 1;
185                 break;
186                 default:
187                         nr = type;
188                         stop = 0;
189         }
190
191         /* Look for the requested number of CR. */
192         while ((cr != nr) && (addr < INVENTORYDATASIZE)) {
193                 if ((buf[addr] == '\r')) {
194                         cr++;
195                 }
196                 addr++;
197         }
198
199         /*
200          * the expected number of CR was found until the end of the IVM
201          *  content --> fill string
202          */
203         if (addr < INVENTORYDATASIZE) {
204                 /* Copy the IVM string in the corresponding string */
205                 for (; (buf[addr] != '\r')                      &&
206                         ((buf[addr] != ';') ||  (!stop))        &&
207                         (size < (maxlen - 1)                    &&
208                         (addr < INVENTORYDATASIZE)); addr++)
209                 {
210                         size += sprintf((char *)string + size, "%c",
211                                                 convert_char (buf[addr]));
212                 }
213
214                 /*
215                  * copy phase is done: check if everything is ok. If not,
216                  * the inventory data is most probably corrupted: tell
217                  * the world there is a problem!
218                  */
219                 if (addr == INVENTORYDATASIZE) {
220                         xcode = -1;
221                         printf("Error end of string not found\n");
222                 } else if ((size >= (maxlen - 1)) &&
223                            (buf[addr] != '\r')) {
224                         xcode = -1;
225                         printf("string too long till next CR\n");
226                 }
227         } else {
228                 /*
229                  * some CR are missing...
230                  * the inventory data is most probably corrupted
231                  */
232                 xcode = -1;
233                 printf("not enough cr found\n");
234         }
235         return xcode;
236 }
237
238 #define GET_STRING(name, which, len) \
239         if (ivm_findinventorystring(which, valbuf, len, buf) == 0) { \
240                 ivm_set_value(name, (char *)valbuf); \
241         }
242
243 static int ivm_check_crc(unsigned char *buf, int block)
244 {
245         unsigned long   crc;
246         unsigned long   crceeprom;
247
248         crc = ivm_calc_crc(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2);
249         crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \
250                         buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256);
251         if (crc != crceeprom) {
252                 if (block == 0)
253                         printf("Error CRC Block: %d EEprom: calculated: \
254                         %lx EEprom: %lx\n", block, crc, crceeprom);
255                 return -1;
256         }
257         return 0;
258 }
259
260 static int ivm_analyze_block2(unsigned char *buf, int len)
261 {
262         unsigned char   valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
263         unsigned long   count;
264
265         /* IVM_MacAddress */
266         sprintf((char *)valbuf, "%pM", buf);
267         ivm_set_value("IVM_MacAddress", (char *)valbuf);
268         /* if an offset is defined, add it */
269 #if defined(CONFIG_PIGGY_MAC_ADRESS_OFFSET)
270         if (CONFIG_PIGGY_MAC_ADRESS_OFFSET > 0) {
271                 unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6];
272
273                 val += CONFIG_PIGGY_MAC_ADRESS_OFFSET;
274                 buf[4] = (val >> 16) & 0xff;
275                 buf[5] = (val >> 8) & 0xff;
276                 buf[6] = val & 0xff;
277                 sprintf((char *)valbuf, "%pM", buf);
278         }
279 #endif
280         if (getenv("ethaddr") == NULL)
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");