xref: /openbmc/u-boot/board/keymile/common/common.c (revision cd8c8775)
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");
719