xref: /rk3399_rockchip-uboot/board/keymile/common/common.c (revision e8195825716c0ef8cfaea513c8a3d9d3becf7e00)
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 				 * store the values in environment variables
835 				 * and save the environment.
836 				 * This can only happen once for the lifetime
837 				 * of a board, because once saved the function
838 				 * will never reach the while loop.
839 				 */
840 				if ((bid == ivmbid) && (hwkey == ivmhwkey)) {
841 					char buf[10];
842 
843 					found = 1;
844 					envbid   = bid;
845 					envhwkey = hwkey;
846 					sprintf(buf, "%lx", bid);
847 					setenv("boardid", buf);
848 					sprintf(buf, "%lx", hwkey);
849 					setenv("hwkey", buf);
850 					saveenv();
851 				}
852 			} /* end while( ! found ) */
853 		}
854 	}
855 
856 	/* compare now the values */
857 	if ((ivmbid == envbid) && (ivmhwkey == envhwkey)) {
858 		printf("boardid=0x%3lX, hwkey=%ld\n", envbid, envhwkey);
859 		rc = 0; /* match */
860 	} else {
861 		printf("Error: env bId=0x%3lX, hwKey=%ld\n", envbid, envhwkey);
862 		printf("       IVM bId=0x%3lX, hwKey=%ld\n", ivmbid, ivmhwkey);
863 		rc = 1; /* don't match */
864 	}
865 	return rc;
866 }
867 
868 U_BOOT_CMD(km_checkbidhwk, 2, 0, do_checkboardidhwk,
869 		"check boardid and hwkey",
870 		"[v]\n  - check environment parameter "\
871 		"\"boardIdListHex\" against stored boardid and hwkey "\
872 		"from the IVM\n    v: verbose output"
873 );
874