Merge branch 'master' of git://git.denx.de/u-boot-arm
diff --git a/MAINTAINERS b/MAINTAINERS
index a394ac9..aabd871 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -305,6 +305,10 @@
 
 	PPChameleonEVB	PPC405EP
 
+Tirumala Marri <tmarri@apm.com>
+
+	bluestone       APM821XX
+
 Reinhard Meyer <r.meyer@emk-elektronik.de>
 
 	TOP860		MPC860T
@@ -343,6 +347,10 @@
 	sbc8240		MPC8240
 	sbc405		PPC405GP
 
+Sergei Poselenov <sposelenov@emcraft.com>
+
+	a4m072		MPC5200
+
 Sudhakar Rajashekhara <sudhakar.raj@ti.com>
 
 	da850evm	ARM926EJS (DA850/OMAP-L138)
@@ -498,10 +506,6 @@
 
 	inka4x0		MPC5200
 
-Tirumala Marri <tmarri@apm.com>
-
-	bluestone       APM821XX
-
 -------------------------------------------------------------------------
 
 Unknown / orphaned boards:
diff --git a/README b/README
index f997a5d..197804e 100644
--- a/README
+++ b/README
@@ -2534,18 +2534,32 @@
 	- CONFIG_ENV_SIZE:
 
 	  These two #defines specify the offset and size of the environment
-	  area within the first NAND device.
+	  area within the first NAND device.  CONFIG_ENV_OFFSET must be
+	  aligned to an erase block boundary.
 
-	- CONFIG_ENV_OFFSET_REDUND
+	- CONFIG_ENV_OFFSET_REDUND (optional):
 
 	  This setting describes a second storage area of CONFIG_ENV_SIZE
-	  size used to hold a redundant copy of the environment data,
-	  so that there is a valid backup copy in case there is a
-	  power failure during a "saveenv" operation.
+	  size used to hold a redundant copy of the environment data, so
+	  that there is a valid backup copy in case there is a power failure
+	  during a "saveenv" operation.  CONFIG_ENV_OFFSET_RENDUND must be
+	  aligned to an erase block boundary.
 
-	Note: CONFIG_ENV_OFFSET and CONFIG_ENV_OFFSET_REDUND must be aligned
-	to a block boundary, and CONFIG_ENV_SIZE must be a multiple of
-	the NAND devices block size.
+	- CONFIG_ENV_RANGE (optional):
+
+	  Specifies the length of the region in which the environment
+	  can be written.  This should be a multiple of the NAND device's
+	  block size.  Specifying a range with more erase blocks than
+	  are needed to hold CONFIG_ENV_SIZE allows bad blocks within
+	  the range to be avoided.
+
+	- CONFIG_ENV_OFFSET_OOB (optional):
+
+	  Enables support for dynamically retrieving the offset of the
+	  environment from block zero's out-of-band data.  The
+	  "nand env.oob" command can be used to record this offset.
+	  Currently, CONFIG_ENV_OFFSET_REDUND is not supported when
+	  using CONFIG_ENV_OFFSET_OOB.
 
 - CONFIG_NAND_ENV_DST
 
diff --git a/arch/arm/include/asm/arch-davinci/emac_defs.h b/arch/arm/include/asm/arch-davinci/emac_defs.h
index 35a1585..76493a1 100644
--- a/arch/arm/include/asm/arch-davinci/emac_defs.h
+++ b/arch/arm/include/asm/arch-davinci/emac_defs.h
@@ -367,7 +367,6 @@
 
 int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data);
 int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data);
-void davinci_eth_set_mac_addr(const u_int8_t *addr);
 
 typedef struct
 {
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index 5f2dfd0..22bd2c9 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -409,15 +409,6 @@
 	enable_interrupts ();
 
 	/* Perform network card initialisation if necessary */
-#ifdef CONFIG_DRIVER_TI_EMAC
-	/* XXX: this needs to be moved to board init */
-extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
-	if (getenv ("ethaddr")) {
-		uchar enetaddr[6];
-		eth_getenv_enetaddr("ethaddr", enetaddr);
-		davinci_eth_set_mac_addr(enetaddr);
-	}
-#endif
 
 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
 	/* XXX: this needs to be moved to board init */
@@ -821,16 +812,6 @@
 	enable_interrupts ();
 
 	/* Perform network card initialisation if necessary */
-#ifdef CONFIG_DRIVER_TI_EMAC
-	/* XXX: this needs to be moved to board init */
-extern void davinci_eth_set_mac_addr (const u_int8_t *addr);
-	if (getenv ("ethaddr")) {
-		uchar enetaddr[6];
-		eth_getenv_enetaddr("ethaddr", enetaddr);
-		davinci_eth_set_mac_addr(enetaddr);
-	}
-#endif
-
 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
 	/* XXX: this needs to be moved to board init */
 	if (getenv ("ethaddr")) {
diff --git a/arch/microblaze/cpu/start.S b/arch/microblaze/cpu/start.S
index 2e9a08d..7f60434 100644
--- a/arch/microblaze/cpu/start.S
+++ b/arch/microblaze/cpu/start.S
@@ -32,6 +32,22 @@
 	mts	rmsr, r0	/* disable cache */
 	addi	r1, r0, CONFIG_SYS_INIT_SP_OFFSET
 	addi	r1, r1, -4	/* Decrement SP to top of memory */
+
+	/* Find-out if u-boot is running on BIG/LITTLE endian platform
+	 * There are some steps which is necessary to keep in mind:
+	 * 1. Setup offset value to r6
+	 * 2. Store word offset value to address 0x0
+	 * 3. Load just byte from address 0x0
+	 * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
+	 *     value that's why is on address 0x0
+	 * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
+	 */
+	addik	r6, r0, 0x2 /* BIG/LITTLE endian offset */
+	swi	r6, r0, 0
+	lbui	r10, r0, 0
+	swi	r6, r0, 0x40
+	swi	r10, r0, 0x50
+
 	/* add opcode instruction for 32bit jump - 2 instruction imm & brai*/
 	addi	r6, r0, 0xb0000000	/* hex b000 opcode imm */
 	swi	r6, r0, 0x0	/* reset address */
@@ -75,26 +91,52 @@
 	/* user_vector_exception */
 	addik	r6, r0, _exception_handler
 	sw	r6, r1, r0
-	lhu	r7, r1, r0
-	shi	r7, r0, 0xa
-	shi	r6, r0, 0xe
+	/*
+	 * BIG ENDIAN memory map for user exception
+	 * 0x8: 0xB000XXXX
+	 * 0xC: 0xB808XXXX
+	 *
+	 * then it is necessary to count address for storing the most significant
+	 * 16bits from _exception_handler address and copy it to 
+	 * 0xa address. Big endian use offset in r10=0 that's why is it just
+	 * 0xa address. The same is done for the least significant 16 bits
+	 * for 0xe address.
+	 *
+	 * LITTLE ENDIAN memory map for user exception
+	 * 0x8: 0xXXXX00B0
+	 * 0xC: 0xXXXX08B8
+	 *
+	 * Offset is for little endian setup to 0x2. rsubi instruction decrease
+	 * address value to ensure that points to proper place which is
+	 * 0x8 for the most significant 16 bits and
+	 * 0xC for the least significant 16 bits
+	 */
+	lhu	r7, r1, r10
+	rsubi	r8, r10, 0xa
+	sh	r7, r0, r8
+	rsubi	r8, r10, 0xe
+	sh	r6, r0, r8
 #endif
 
 #ifdef CONFIG_SYS_INTC_0
 	/* interrupt_handler */
 	addik	r6, r0, _interrupt_handler
 	sw	r6, r1, r0
-	lhu	r7, r1, r0
-	shi	r7, r0, 0x12
-	shi	r6, r0, 0x16
+	lhu	r7, r1, r10
+	rsubi	r8, r10, 0x12
+	sh	r7, r0, r8
+	rsubi	r8, r10, 0x16
+	sh	r6, r0, r8
 #endif
 
 	/* hardware exception */
 	addik	r6, r0, _hw_exception_handler
 	sw	r6, r1, r0
-	lhu	r7, r1, r0
-	shi	r7, r0, 0x22
-	shi	r6, r0, 0x26
+	lhu	r7, r1, r10
+	rsubi	r8, r10, 0x22
+	sh	r7, r0, r8
+	rsubi	r8, r10, 0x26
+	sh	r6, r0, r8
 
 	/* enable instruction and data cache */
 	mfs	r12, rmsr
diff --git a/arch/microblaze/include/asm/byteorder.h b/arch/microblaze/include/asm/byteorder.h
index a4a75b7..b2757a4 100644
--- a/arch/microblaze/include/asm/byteorder.h
+++ b/arch/microblaze/include/asm/byteorder.h
@@ -50,6 +50,10 @@
 
 #endif /* __GNUC__ */
 
+#ifdef __MICROBLAZEEL__
+#include <linux/byteorder/little_endian.h>
+#else
 #include <linux/byteorder/big_endian.h>
+#endif
 
 #endif /* __MICROBLAZE_BYTEORDER_H__ */
diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c
index 3ff5c17..0ce040e 100644
--- a/arch/microblaze/lib/board.c
+++ b/arch/microblaze/lib/board.c
@@ -31,6 +31,7 @@
 #include <version.h>
 #include <watchdog.h>
 #include <stdio_dev.h>
+#include <net.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -42,6 +43,7 @@
 #ifdef CONFIG_SYS_INTC_0
 extern int interrupts_init (void);
 #endif
+
 #if defined(CONFIG_CMD_NET)
 extern int eth_init (bd_t * bis);
 #endif
@@ -165,8 +167,14 @@
 
 #if defined(CONFIG_CMD_NET)
 	/* IP Address */
-	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
-	eth_init (bd);
+	bd->bi_ip_addr = getenv_IPaddr("ipaddr");
+
+	printf("Net:   ");
+	eth_initialize(gd->bd);
+
+	uchar enetaddr[6];
+	eth_getenv_enetaddr("ethaddr", enetaddr);
+	printf("MAC:   %pM\n", enetaddr);
 #endif
 
 	/* main_loop */
diff --git a/arch/powerpc/cpu/74xx_7xx/start.S b/arch/powerpc/cpu/74xx_7xx/start.S
index a36af5a..47694aa 100644
--- a/arch/powerpc/cpu/74xx_7xx/start.S
+++ b/arch/powerpc/cpu/74xx_7xx/start.S
@@ -94,17 +94,7 @@
 	. = EXC_OFF_SYS_RESET
 	.globl	_start
 _start:
-	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH */
 	b	boot_cold
-	sync
-
-	. = EXC_OFF_SYS_RESET + 0x10
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM	/* Software reboot		*/
-	b	boot_warm
-	sync
 
 	/* the boot code is located below the exception table */
 
@@ -188,7 +178,6 @@
 	. = 0x2000
 
 boot_cold:
-boot_warm:
 	/* disable everything */
 	li	r0, 0
 	mtspr	HID0, r0
@@ -288,14 +277,11 @@
 	bl	cpu_init_f
 	sync
 
-	mr	r3, r21
-
-	/* r3: BOOTFLAG */
 	/* run 1st part of board init code (from Flash)   */
 	bl	board_init_f
 	sync
 
-	/* NOTREACHED */
+	/* NOTREACHED - board_init_f() does not return */
 
 	.globl	invalidate_bats
 invalidate_bats:
diff --git a/arch/powerpc/cpu/mpc512x/start.S b/arch/powerpc/cpu/mpc512x/start.S
index d26b617..1047c51 100644
--- a/arch/powerpc/cpu/mpc512x/start.S
+++ b/arch/powerpc/cpu/mpc512x/start.S
@@ -100,7 +100,6 @@
 	.globl	_start
 	/* Start from here after reset/power on */
 _start:
-	li	r21, BOOTFLAG_COLD  /* Normal Power-On: Boot from FLASH */
 	b	boot_cold
 
 	.globl	_start_of_vectors
@@ -260,8 +259,6 @@
 	/* run low-level CPU init code (in Flash) */
 	bl	cpu_init_f
 
-	/* r3: BOOTFLAG */
-	mr	r3, r21
 	/* run 1st part of board init code (in Flash) */
 	bl	board_init_f
 
diff --git a/arch/powerpc/cpu/mpc5xx/start.S b/arch/powerpc/cpu/mpc5xx/start.S
index 0af879e..4fd9b63 100644
--- a/arch/powerpc/cpu/mpc5xx/start.S
+++ b/arch/powerpc/cpu/mpc5xx/start.S
@@ -91,18 +91,6 @@
 	li	r4, CONFIG_SYS_ISB			/* Set ISB bit */
 	or	r3, r3, r4
 	mtspr	638, r3
-	li	r21, BOOTFLAG_COLD		/* Normal Power-On: Boot from FLASH	*/
-	b	boot_cold
-
-	. = EXC_OFF_SYS_RESET + 0x20
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM		/* Software reboot */
-	b	boot_warm
-
-boot_cold:
-boot_warm:
 
 	/* Initialize machine status; enable machine check interrupt		*/
 	/*----------------------------------------------------------------------*/
@@ -188,10 +176,10 @@
 	/* r3: IMMR */
 	bl	cpu_init_f	/* run low-level CPU init code     (from Flash)	*/
 
-	mr	r3, r21
-	/* r3: BOOTFLAG */
 	bl	board_init_f	/* run 1st part of board init code (from Flash) */
 
+	/* NOTREACHED - board_init_f() does not return */
+
 
 	.globl	_start_of_vectors
 _start_of_vectors:
diff --git a/arch/powerpc/cpu/mpc5xxx/start.S b/arch/powerpc/cpu/mpc5xxx/start.S
index 8b9f09b..1385869 100644
--- a/arch/powerpc/cpu/mpc5xxx/start.S
+++ b/arch/powerpc/cpu/mpc5xxx/start.S
@@ -89,19 +89,6 @@
 	. = EXC_OFF_SYS_RESET
 	.globl	_start
 _start:
-	li	r21, BOOTFLAG_COLD	/* Normal Power-On		*/
-	nop
-	b	boot_cold
-
-	. = EXC_OFF_SYS_RESET + 0x10
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM	/* Software reboot		*/
-	b	boot_warm
-
-boot_cold:
-boot_warm:
 	mfmsr	r5			/* save msr contents		*/
 
 	/* Move CSBoot and adjust instruction pointer                   */
@@ -175,10 +162,10 @@
 	/* r3: IMMR */
 	bl	cpu_init_f	/* run low-level CPU init code (in Flash)*/
 
-	mr	r3, r21
-	/* r3: BOOTFLAG */
 	bl	board_init_f	/* run 1st part of board init code (in Flash)*/
 
+	/* NOTREACHED - board_init_f() does not return */
+
 /*
  * Vector Table
  */
diff --git a/arch/powerpc/cpu/mpc8220/start.S b/arch/powerpc/cpu/mpc8220/start.S
index 3d79d8e..c156e25 100644
--- a/arch/powerpc/cpu/mpc8220/start.S
+++ b/arch/powerpc/cpu/mpc8220/start.S
@@ -88,19 +88,6 @@
 	. = EXC_OFF_SYS_RESET
 	.globl	_start
 _start:
-	li	r21, BOOTFLAG_COLD  /* Normal Power-On	    */
-	nop
-	b	boot_cold
-
-	. = EXC_OFF_SYS_RESET + 0x10
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM  /* Software reboot	    */
-	b	boot_warm
-
-boot_cold:
-boot_warm:
 	mfmsr	r5		    /* save msr contents    */
 
 	/* replace default MBAR base address from 0x80000000
@@ -144,10 +131,10 @@
 	/* r3: IMMR */
 	bl	cpu_init_f	/* run low-level CPU init code (in Flash)*/
 
-	mr	r3, r21
-	/* r3: BOOTFLAG */
 	bl	board_init_f	/* run 1st part of board init code (in Flash)*/
 
+	/* NOTREACHED - board_init_f() does not return */
+
 /*
  * Vector Table
  */
diff --git a/arch/powerpc/cpu/mpc824x/start.S b/arch/powerpc/cpu/mpc824x/start.S
index f3f595a..5b126bb 100644
--- a/arch/powerpc/cpu/mpc824x/start.S
+++ b/arch/powerpc/cpu/mpc824x/start.S
@@ -97,19 +97,6 @@
 	. = EXC_OFF_SYS_RESET
 	.globl	_start
 _start:
-	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH	*/
-	b	boot_cold
-
-	. = EXC_OFF_SYS_RESET + 0x10
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM	/* Software reboot			*/
-	b	boot_warm
-
-boot_cold:
-boot_warm:
-
 	/* Initialize machine status; enable machine check interrupt		*/
 	/*----------------------------------------------------------------------*/
 	li	r3, MSR_KERNEL		/* Set FP, ME, RI flags */
@@ -198,10 +185,10 @@
 	/* r3: IMMR */
 	bl	cpu_init_f	/* run low-level CPU init code     (from Flash)	*/
 
-	mr	r3, r21
-	/* r3: BOOTFLAG */
 	bl	board_init_f	/* run 1st part of board init code (from Flash) */
 
+	/* NOTREACHED - board_init_f() does not return */
+
 
 	.globl	_start_of_vectors
 _start_of_vectors:
diff --git a/arch/powerpc/cpu/mpc8260/start.S b/arch/powerpc/cpu/mpc8260/start.S
index a435042..9485afa 100644
--- a/arch/powerpc/cpu/mpc8260/start.S
+++ b/arch/powerpc/cpu/mpc8260/start.S
@@ -161,18 +161,6 @@
 
 	.globl	_start
 _start:
-	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH*/
-	nop
-	b	boot_cold
-
-	. = EXC_OFF_SYS_RESET + 0x10
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM	/* Software reboot		*/
-	b	boot_warm
-
-boot_cold:
 #if defined(CONFIG_MPC8260ADS) && defined(CONFIG_SYS_DEFAULT_IMMR)
 	lis	r3, CONFIG_SYS_DEFAULT_IMMR@h
 	nop
@@ -185,7 +173,7 @@
 	stw	r4, 0(r3)
 	nop
 #endif /* CONFIG_MPC8260ADS && CONFIG_SYS_DEFAULT_IMMR */
-boot_warm:
+
 	mfmsr	r5			/* save msr contents		*/
 
 #if defined(CONFIG_COGENT)
@@ -254,10 +242,10 @@
 	bl	init_debug	/* set up debugging stuff		*/
 #endif
 
-	mr	r3, r21
-	/* r3: BOOTFLAG */
 	bl	board_init_f	/* run 1st part of board init code (in Flash)*/
 
+	/* NOTREACHED - board_init_f() does not return */
+
 /*
  * Vector Table
  */
diff --git a/arch/powerpc/cpu/mpc83xx/start.S b/arch/powerpc/cpu/mpc83xx/start.S
index c7d85a8..bdce915 100644
--- a/arch/powerpc/cpu/mpc83xx/start.S
+++ b/arch/powerpc/cpu/mpc83xx/start.S
@@ -183,22 +183,9 @@
 
 	.globl	_start
 _start: /* time t 0 */
-	li	r21, BOOTFLAG_COLD  /* Normal Power-On: Boot from FLASH*/
-	nop
-	b	boot_cold
-
-	. = EXC_OFF_SYS_RESET + 0x10
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM	/* Software reboot	*/
-	b	boot_warm
-
-
-boot_cold: /* time t 3 */
 	lis	r4, CONFIG_DEFAULT_IMMR@h
 	nop
-boot_warm: /* time t 5 */
+
 	mfmsr	r5			/* save msr contents	*/
 
 	/* 83xx manuals prescribe a specific sequence for updating IMMRBAR. */
@@ -302,11 +289,11 @@
 	/* run low-level CPU init code (in Flash)*/
 	bl	cpu_init_f
 
-	/* r3: BOOTFLAG */
-	mr	r3, r21
 	/* run 1st part of board init code (in Flash)*/
 	bl	board_init_f
 
+	/* NOTREACHED - board_init_f() does not return */
+
 #ifndef CONFIG_NAND_SPL
 /*
  * Vector Table
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
index 3278b10..91096ad 100644
--- a/arch/powerpc/cpu/mpc85xx/start.S
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -432,6 +432,8 @@
 	bl	board_init_f
 	isync
 
+	/* NOTREACHED - board_init_f() does not return */
+
 #ifndef CONFIG_NAND_SPL
 	. = EXC_OFF_SYS_RESET
 	.globl	_start_of_vectors
diff --git a/arch/powerpc/cpu/mpc86xx/start.S b/arch/powerpc/cpu/mpc86xx/start.S
index ed1e4ca..596053f 100644
--- a/arch/powerpc/cpu/mpc86xx/start.S
+++ b/arch/powerpc/cpu/mpc86xx/start.S
@@ -83,17 +83,7 @@
 	. = EXC_OFF_SYS_RESET
 	.globl	_start
 _start:
-	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH */
 	b	boot_cold
-	sync
-
-	. = EXC_OFF_SYS_RESET + 0x10
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM	/* Software reboot */
-	b	boot_warm
-	sync
 
 	/* the boot code is located below the exception table */
 
@@ -166,7 +156,6 @@
 	. = 0x2000
 
 boot_cold:
-boot_warm:
 	/*
 	 * NOTE: Only Cpu 0 will ever come here.  Other cores go to an
 	 * address specified by the BPTR
@@ -303,14 +292,12 @@
 #endif
 
 /*	bl	l2cache_enable */
-	mr	r3, r21
 
-	/* r3: BOOTFLAG */
 	/* run 1st part of board init code (from Flash)	  */
 	bl	board_init_f
 	sync
 
-	/* NOTREACHED */
+	/* NOTREACHED - board_init_f() does not return */
 
 	.globl	invalidate_bats
 invalidate_bats:
diff --git a/arch/powerpc/cpu/mpc8xx/start.S b/arch/powerpc/cpu/mpc8xx/start.S
index 7cf602f..d6100ec 100644
--- a/arch/powerpc/cpu/mpc8xx/start.S
+++ b/arch/powerpc/cpu/mpc8xx/start.S
@@ -96,18 +96,6 @@
 _start:
 	lis	r3, CONFIG_SYS_IMMR@h		/* position IMMR */
 	mtspr	638, r3
-	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH	*/
-	b	boot_cold
-
-	. = EXC_OFF_SYS_RESET + 0x10
-
-	.globl	_start_warm
-_start_warm:
-	li	r21, BOOTFLAG_WARM	/* Software reboot			*/
-	b	boot_warm
-
-boot_cold:
-boot_warm:
 
 	/* Initialize machine status; enable machine check interrupt		*/
 	/*----------------------------------------------------------------------*/
@@ -202,10 +190,10 @@
 	/* r3: IMMR */
 	bl	cpu_init_f	/* run low-level CPU init code     (from Flash)	*/
 
-	mr	r3, r21
-	/* r3: BOOTFLAG */
 	bl	board_init_f	/* run 1st part of board init code (from Flash) */
 
+	/* NOTREACHED - board_init_f() does not return */
+
 
 	.globl	_start_of_vectors
 _start_of_vectors:
diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S
index c2d52bf..03bde4d 100644
--- a/arch/powerpc/cpu/ppc4xx/start.S
+++ b/arch/powerpc/cpu/ppc4xx/start.S
@@ -261,6 +261,7 @@
 	GET_GOT
 	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
 	bl	board_init_f
+	/* NOTREACHED - board_init_f() does not return */
 #endif
 
 #if defined(CONFIG_SYS_RAMBOOT)
@@ -803,6 +804,7 @@
 
 	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
 	bl	board_init_f
+	/* NOTREACHED - board_init_f() does not return */
 #endif
 
 #endif /* CONFIG_440 */
@@ -911,6 +913,7 @@
 	GET_GOT			/* initialize GOT access			*/
 
 	bl	board_init_f	/* run first part of init code (from Flash)	*/
+	/* NOTREACHED - board_init_f() does not return */
 
 #endif	/* CONFIG_IOP480 */
 
@@ -1180,8 +1183,9 @@
 
 	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
 
-	/* NEVER RETURNS! */
 	bl	board_init_f	/* run first part of init code (from Flash)	*/
+	/* NOTREACHED - board_init_f() does not return */
+
 #endif /* CONFIG_NAND_SPL */
 
 #endif	/* CONFIG_405GP || CONFIG_405CR || CONFIG_405 || CONFIG_405EP */
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
index bfdfa86..529f719 100644
--- a/arch/powerpc/lib/board.c
+++ b/arch/powerpc/lib/board.c
@@ -480,6 +480,7 @@
 	 */
 	addr_sp -= sizeof (bd_t);
 	bd = (bd_t *) addr_sp;
+	memset(bd, 0, sizeof(bd_t));
 	gd->bd = bd;
 	debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
 			sizeof (bd_t), addr_sp);
@@ -512,9 +513,6 @@
 #ifdef CONFIG_SYS_SRAM_BASE
 	bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;	/* start of  SRAM memory	*/
 	bd->bi_sramsize  = CONFIG_SYS_SRAM_SIZE;	/* size  of  SRAM memory	*/
-#else
-	bd->bi_sramstart = 0;
-	bd->bi_sramsize  = 0;
 #endif
 
 #if defined(CONFIG_8xx) || defined(CONFIG_8260) || defined(CONFIG_5xx) || \
@@ -739,14 +737,7 @@
 	bd->bi_flashoffset = TEXT_BASE + flash_size;
 # elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
 	bd->bi_flashoffset = monitor_flash_len;	/* reserved area for startup monitor  */
-# else
-	bd->bi_flashoffset = 0;
 # endif
-#else	/* CONFIG_SYS_NO_FLASH */
-
-	bd->bi_flashsize = 0;
-	bd->bi_flashstart = 0;
-	bd->bi_flashoffset = 0;
 #endif /* !CONFIG_SYS_NO_FLASH */
 
 	WATCHDOG_RESET ();
@@ -803,14 +794,8 @@
 		if (s && ((*s == 'y') || (*s == 'Y'))) {
 			bd->bi_iic_fast[0] = 1;
 			bd->bi_iic_fast[1] = 1;
-		} else {
-			bd->bi_iic_fast[0] = 0;
-			bd->bi_iic_fast[1] = 0;
 		}
 	}
-#else
-	bd->bi_iic_fast[0] = 0;
-	bd->bi_iic_fast[1] = 0;
 #endif	/* CONFIG_I2CFAST */
 #endif	/* CONFIG_405GP, CONFIG_405EP */
 #endif	/* CONFIG_SYS_EXTBDINFO */
diff --git a/board/a4m072/Makefile b/board/a4m072/Makefile
new file mode 100644
index 0000000..442e2d0
--- /dev/null
+++ b/board/a4m072/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib$(BOARD).a
+
+COBJS	:= $(BOARD).o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak $(obj).depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/a4m072/a4m072.c b/board/a4m072/a4m072.c
new file mode 100644
index 0000000..ae7ccbb
--- /dev/null
+++ b/board/a4m072/a4m072.c
@@ -0,0 +1,506 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
+ *
+ * (C) Copyright 2010
+ * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <libfdt.h>
+#include <netdev.h>
+#include <led-display.h>
+#include <linux/err.h>
+
+#include "mt46v32m16.h"
+
+#ifndef CONFIG_SYS_RAMBOOT
+static void sdram_start (int hi_addr)
+{
+	long hi_addr_bit = hi_addr ? 0x01000000 : 0;
+	long control = SDRAM_CONTROL | hi_addr_bit;
+
+	/* unlock mode register */
+	out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000000);
+	__asm__ volatile ("sync");
+
+	/* precharge all banks */
+	out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000002);
+	__asm__ volatile ("sync");
+
+#if SDRAM_DDR
+	/* set mode register: extended mode */
+	out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_EMODE);
+	__asm__ volatile ("sync");
+
+	/* set mode register: reset DLL */
+	out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_MODE | 0x04000000);
+	__asm__ volatile ("sync");
+#endif
+
+	/* precharge all banks */
+	out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000002);
+	__asm__ volatile ("sync");
+
+	/* auto refresh */
+	out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000004);
+	__asm__ volatile ("sync");
+
+	/* set mode register */
+	out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_MODE);
+	__asm__ volatile ("sync");
+
+	/* normal operation */
+	out_be32((void *)MPC5XXX_SDRAM_CTRL, control);
+	__asm__ volatile ("sync");
+}
+#endif
+
+/*
+ * ATTENTION: Although partially referenced initdram does NOT make real use
+ *            use of CONFIG_SYS_SDRAM_BASE. The code does not work if CONFIG_SYS_SDRAM_BASE
+ *            is something else than 0x00000000.
+ */
+
+phys_size_t initdram (int board_type)
+{
+	ulong dramsize = 0;
+	uint svr, pvr;
+
+#ifndef CONFIG_SYS_RAMBOOT
+	ulong test1, test2;
+
+	/* setup SDRAM chip selects */
+	out_be32((void *)MPC5XXX_SDRAM_CS0CFG, 0x0000001e); /* 2GB at 0x0 */
+	out_be32((void *)MPC5XXX_SDRAM_CS1CFG, 0x80000000); /* disabled */
+	__asm__ volatile ("sync");
+
+	/* setup config registers */
+	out_be32((void *)MPC5XXX_SDRAM_CONFIG1, SDRAM_CONFIG1);
+	out_be32((void *)MPC5XXX_SDRAM_CONFIG2, SDRAM_CONFIG2);
+	__asm__ volatile ("sync");
+
+#if SDRAM_DDR
+	/* set tap delay */
+	out_be32((void *)MPC5XXX_CDM_PORCFG, SDRAM_TAPDELAY);
+	__asm__ volatile ("sync");
+#endif
+
+	/* find RAM size using SDRAM CS0 only */
+	sdram_start(0);
+	test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
+	sdram_start(1);
+	test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
+	if (test1 > test2) {
+		sdram_start(0);
+		dramsize = test1;
+	} else {
+		dramsize = test2;
+	}
+
+	/* memory smaller than 1MB is impossible */
+	if (dramsize < (1 << 20)) {
+		dramsize = 0;
+	}
+
+	/* set SDRAM CS0 size according to the amount of RAM found */
+	if (dramsize > 0) {
+		out_be32((void *)MPC5XXX_SDRAM_CS0CFG,
+				 0x13 + __builtin_ffs(dramsize >> 20) - 1);
+	} else {
+		out_be32((void *)MPC5XXX_SDRAM_CS0CFG, 0); /* disabled */
+	}
+
+#else /* CONFIG_SYS_RAMBOOT */
+
+	/* retrieve size of memory connected to SDRAM CS0 */
+	dramsize = in_be32((void *)MPC5XXX_SDRAM_CS0CFG) & 0xFF;
+	if (dramsize >= 0x13) {
+		dramsize = (1 << (dramsize - 0x13)) << 20;
+	} else {
+		dramsize = 0;
+	}
+
+#endif /* CONFIG_SYS_RAMBOOT */
+
+	/*
+	 * On MPC5200B we need to set the special configuration delay in the
+	 * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM
+	 * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190:
+	 *
+	 * "The SDelay should be written to a value of 0x00000004. It is
+	 * required to account for changes caused by normal wafer processing
+	 * parameters."
+	 */
+	svr = get_svr();
+	pvr = get_pvr();
+	if ((SVR_MJREV(svr) >= 2) &&
+	    (PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4)) {
+
+		out_be32((void *)MPC5XXX_SDRAM_SDELAY, 0x04);
+		__asm__ volatile ("sync");
+	}
+
+	return dramsize;
+}
+
+int checkboard (void)
+{
+	puts ("Board: A4M072\n");
+	return 0;
+}
+
+#ifdef	CONFIG_PCI
+static struct pci_controller hose;
+
+extern void pci_mpc5xxx_init(struct pci_controller *);
+
+void pci_init_board(void)
+{
+	pci_mpc5xxx_init(&hose);
+}
+#endif
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+void
+ft_board_setup(void *blob, bd_t *bd)
+{
+	ft_cpu_setup(blob, bd);
+}
+#endif
+
+int board_eth_init(bd_t *bis)
+{
+	int rv, num_if = 0;
+
+	/* Initialize TSECs first */
+	if ((rv = cpu_eth_init(bis)) >= 0)
+		num_if += rv;
+	else
+		printf("ERROR: failed to initialize FEC.\n");
+
+	if ((rv = pci_eth_init(bis)) >= 0)
+		num_if += rv;
+	else
+		printf("ERROR: failed to initialize PCI Ethernet.\n");
+
+	return num_if;
+}
+/*
+ * Miscellaneous late-boot configurations
+ *
+ * Initialize EEPROM write-protect GPIO pin.
+ */
+int misc_init_r(void)
+{
+#if defined(CONFIG_SYS_EEPROM_WREN)
+	/* Enable GPIO pin */
+	setbits_be32((void *)MPC5XXX_WU_GPIO_ENABLE, CONFIG_SYS_EEPROM_WP);
+	/* Set direction, output */
+	setbits_be32((void *)MPC5XXX_WU_GPIO_DIR, CONFIG_SYS_EEPROM_WP);
+	/* De-assert write enable */
+	setbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
+#endif
+	return 0;
+}
+#if defined(CONFIG_SYS_EEPROM_WREN)
+/* Input: <dev_addr>  I2C address of EEPROM device to enable.
+ *         <state>     -1: deliver current state
+ *	               0: disable write
+ *		       1: enable write
+ *  Returns:           -1: wrong device address
+ *                      0: dis-/en- able done
+ *		     0/1: current state if <state> was -1.
+ */
+int eeprom_write_enable (unsigned dev_addr, int state)
+{
+	if (CONFIG_SYS_I2C_EEPROM_ADDR != dev_addr) {
+		return -1;
+	} else {
+		switch (state) {
+		case 1:
+			/* Enable write access */
+			clrbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
+			state = 0;
+			break;
+		case 0:
+			/* Disable write access */
+			setbits_be32((void *)MPC5XXX_WU_GPIO_DATA_O, CONFIG_SYS_EEPROM_WP);
+			state = 0;
+			break;
+		default:
+			/* Read current status back. */
+			state = (0 == (in_be32((void *)MPC5XXX_WU_GPIO_DATA_O) &
+						   CONFIG_SYS_EEPROM_WP));
+			break;
+		}
+	}
+	return state;
+}
+#endif
+
+#ifdef CONFIG_CMD_DISPLAY
+#define DISPLAY_BUF_SIZE	2
+static u8 display_buf[DISPLAY_BUF_SIZE];
+static u8 display_putc_pos;
+static u8 display_out_pos;
+
+static u8 display_dot_enable;
+
+void display_set(int cmd) {
+
+	if (cmd & DISPLAY_CLEAR) {
+		display_buf[0] = display_buf[1] = 0;
+	}
+
+	if (cmd & DISPLAY_HOME) {
+		display_putc_pos = 0;
+	}
+
+	if (cmd & DISPLAY_MARK) {
+		display_dot_enable = 1;
+	} else {
+		display_dot_enable = 0;
+	}
+}
+
+#define SEG_A    (1<<0)
+#define SEG_B    (1<<1)
+#define SEG_C    (1<<2)
+#define SEG_D    (1<<3)
+#define SEG_E    (1<<4)
+#define SEG_F    (1<<5)
+#define SEG_G    (1<<6)
+#define SEG_P    (1<<7)
+#define SEG__    0
+
+/*
+ * +- A -+
+ * |     |
+ * F     B
+ * |     |
+ * +- G -+
+ * |     |
+ * E     C
+ * |     |
+ * +- D -+  P
+ *
+ * 0..9		index 0..9
+ * A..Z		index 10..35
+ * -		index 36
+ * _		index 37
+ */
+
+#define SYMBOL_DASH		(36)
+#define SYMBOL_UNDERLINE	(37)
+
+static u8 display_char2seg7_tbl[]=
+{
+	SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,		/* 0 */
+	SEG_B | SEG_C,						/* 1 */
+	SEG_A | SEG_B | SEG_D | SEG_E | SEG_G,			/* 2 */
+	SEG_A | SEG_B | SEG_C | SEG_D | SEG_G,			/* 3 */
+	SEG_B | SEG_C | SEG_F | SEG_G,				/* 4 */
+	SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,			/* 5 */
+	SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,		/* 6 */
+	SEG_A | SEG_B | SEG_C,					/* 7 */
+	SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,	/* 8 */
+	SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,		/* 9 */
+	SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,		/* A */
+	SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,			/* b */
+	SEG_A | SEG_D | SEG_E | SEG_F,				/* C */
+	SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,			/* d */
+	SEG_A | SEG_D | SEG_E | SEG_F | SEG_G,			/* E */
+	SEG_A | SEG_E | SEG_F | SEG_G,				/* F */
+	SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,		/* g */
+	SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,			/* H */
+	SEG_E | SEG_F,						/* I */
+	SEG_B | SEG_C | SEG_D | SEG_E,				/* J */
+	SEG_A,						/* K - special 1 */
+	SEG_D | SEG_E | SEG_F,					/* L */
+	SEG_B,						/* m - special 2 */
+	SEG_C | SEG_E | SEG_G,					/* n */
+	SEG_C | SEG_D | SEG_E | SEG_G,				/* o */
+	SEG_A | SEG_B | SEG_E | SEG_F | SEG_G,			/* P */
+	SEG_A | SEG_B | SEG_C | SEG_F | SEG_G,			/* q */
+	SEG_E | SEG_G,						/* r */
+	SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,			/* S */
+	SEG_D | SEG_E | SEG_F | SEG_G,				/* t */
+	SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,			/* U */
+	SEG_C | SEG_D | SEG_E | SEG_F,				/* V */
+	SEG_C,						/* w - special 3 */
+	SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,			/* X */
+	SEG_B | SEG_C | SEG_D | SEG_F | SEG_G,			/* Y */
+	SEG_A | SEG_B | SEG_D | SEG_E | SEG_G,			/* Z */
+	SEG_G,							/* - */
+	SEG_D							/* _ */
+};
+
+/* Convert char to the LED segments representation */
+static u8 display_char2seg7(char c)
+{
+	u8 val = 0;
+
+	if (c >= '0' && c <= '9')
+		c -= '0';
+	else if (c >= 'a' && c <= 'z')
+		c -= 'a' - 10;
+	else if (c >= 'A' && c <= 'Z')
+		c -= 'A' - 10;
+	else if (c == '-')
+		c = SYMBOL_DASH;
+	else if ((c == '_') || (c == '.'))
+		c = SYMBOL_UNDERLINE;
+	else
+		c = ' ';	/* display unsupported symbols as space */
+
+	if (c != ' ')
+		val = display_char2seg7_tbl[(int)c];
+
+	/* Handle DP LED here */
+	if (display_dot_enable) {
+		val |= SEG_P;
+	}
+
+	return val;
+}
+
+static inline int display_putc_nomark(char c)
+{
+	if (display_putc_pos >= DISPLAY_BUF_SIZE)
+		return -1;
+
+	display_buf[display_putc_pos++] = display_char2seg7(c);
+	/* one-symbol message should be steady */
+	if (display_putc_pos == 1)
+		display_buf[display_putc_pos] = display_char2seg7(c);
+
+	return c;
+}
+
+int display_putc(char c)
+{
+	/* Mark the codes from the "display" command with the DP LED */
+	display_set(DISPLAY_MARK);
+	return display_putc_nomark(c);
+}
+
+/*
+ * Flush current symbol to the LED display hardware
+ */
+static inline void display_flush(void)
+{
+	u32 val = display_buf[display_out_pos];
+
+	val |= (val << 8) | (val << 16) | (val << 24);
+	out_be32((void *)CONFIG_SYS_DISP_CHR_RAM, val);
+}
+
+/*
+ * Output contents of the software display buffer to the LED display every 0.5s
+ */
+void board_show_activity(ulong timestamp)
+{
+	static ulong last;
+	static u8 once;
+
+	if (!once || (timestamp - last >= (CONFIG_SYS_HZ / 2))) {
+		display_flush();
+		display_out_pos ^= 1;
+		last = timestamp;
+		once = 1;
+	}
+}
+
+/*
+ * Empty fake function
+ */
+void show_activity(int arg)
+{
+}
+#endif
+#if defined (CONFIG_SHOW_BOOT_PROGRESS)
+static int a4m072_status2code(int status, char *buf)
+{
+	char c = 0;
+
+	if (((status > 0) && (status <= 8)) ||
+				((status >= 100) && (status <= 108)) ||
+				((status < 0) && (status >= -9)) ||
+				(status == -100) || (status == -101) ||
+				((status <= -103) && (status >= -113))) {
+		c = '5';
+	} else if (((status >= 9) && (status <= 14)) ||
+			((status >= 120) && (status <= 123)) ||
+			((status >= 125) && (status <= 129)) ||
+			((status >= -13) && (status <= -10)) ||
+			(status == -120) || (status == -122) ||
+			((status <= -124) && (status >= -127)) ||
+			(status == -129)) {
+		c = '8';
+	} else if (status == 15) {
+		c = '9';
+	} else if ((status <= -30) && (status >= -32)) {
+		c = 'A';
+	} else if (((status <= -35) && (status >= -40)) ||
+			((status <= -42) && (status >= -51)) ||
+			((status <= -53) && (status >= -58)) ||
+			(status == -64) ||
+			((status <= -80) && (status >= -83)) ||
+			(status == -130) || (status == -140) ||
+			(status == -150)) {
+		c = 'B';
+	}
+
+	if (c == 0)
+		return -EINVAL;
+
+	buf[0] = (status < 0) ? '-' : c;
+	buf[1] = c;
+
+	return 0;
+}
+
+void show_boot_progress(int status)
+{
+	char buf[2];
+
+	if (a4m072_status2code(status, buf) < 0)
+		return;
+
+	display_set(0);	/* Clear DP Led */
+	display_putc_nomark(buf[0]);
+	display_putc_nomark(buf[1]);
+	display_set(DISPLAY_HOME);
+	display_out_pos = 0;	/* reset output position */
+
+	/* we want to flush status 15 now */
+	if (status == 15)
+		display_flush();
+}
+#endif
diff --git a/board/a4m072/config.mk b/board/a4m072/config.mk
new file mode 100644
index 0000000..c6ba51d
--- /dev/null
+++ b/board/a4m072/config.mk
@@ -0,0 +1,39 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# a4m072 board:
+#
+#	Valid values for TEXT_BASE is:
+#
+#	0xFE000000   boot low
+#
+
+sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
+
+ifndef TEXT_BASE
+## Standard: boot low
+TEXT_BASE = 0xFE000000
+endif
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board
diff --git a/board/a4m072/mt46v32m16.h b/board/a4m072/mt46v32m16.h
new file mode 100644
index 0000000..d7561fb
--- /dev/null
+++ b/board/a4m072/mt46v32m16.h
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#define SDRAM_DDR	1		/* is DDR */
+
+#if defined(CONFIG_MPC5200)
+/* Settings for XLB = 132 MHz */
+#define SDRAM_MODE	0x018D0000
+#define SDRAM_EMODE	0x40010000
+#define SDRAM_CONTROL	0x704f0f00
+#define SDRAM_CONFIG1	0x73722930
+#define SDRAM_CONFIG2	0x47770000
+#define SDRAM_TAPDELAY	0x10000000
+
+#else
+#error CONFIG_MPC5200 not defined
+#endif
diff --git a/board/davinci/common/misc.c b/board/davinci/common/misc.c
index 86a875e..b60a46e 100644
--- a/board/davinci/common/misc.c
+++ b/board/davinci/common/misc.c
@@ -85,45 +85,22 @@
 	return 0;
 }
 
-/* If there is a MAC address in the environment, and if it is not identical to
- * the MAC address in the EEPROM, then a warning is printed and the MAC address
- * from the environment is used.
- *
+/*
  * If there is no MAC address in the environment, then it will be initialized
  * (silently) from the value in the EEPROM.
  */
-void dv_configure_mac_address(uint8_t *rom_enetaddr)
+void davinci_sync_env_enetaddr(uint8_t *rom_enetaddr)
 {
-	int i;
-	u_int8_t env_enetaddr[6];
-	char *tmp = getenv("ethaddr");
-	char *end;
+	uint8_t env_enetaddr[6];
 
-	/* Read Ethernet MAC address from the U-Boot environment.
-	 * If it is not defined, env_enetaddr[] will be cleared. */
-	for (i = 0; i < 6; i++) {
-		env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
-		if (tmp)
-			tmp = (*end) ? end+1 : end;
-	}
-
-	/* Check if EEPROM and U-Boot environment MAC addresses match. */
-	if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6) != 0 &&
-	    memcmp(env_enetaddr, rom_enetaddr, 6) != 0) {
-		printf("Warning: MAC addresses don't match:\n");
-		printf("  EEPROM MAC address: %pM\n", rom_enetaddr);
-		printf("     \"ethaddr\" value: %pM\n", env_enetaddr) ;
-		debug("### Using MAC address from environment\n");
-	}
-	if (!tmp) {
-		char ethaddr[20];
-
+	eth_getenv_enetaddr_by_index(0, env_enetaddr);
+	if (!memcmp(env_enetaddr, "\0\0\0\0\0\0", 6)) {
 		/* There is no MAC address in the environment, so we initialize
 		 * it from the value in the EEPROM. */
-		sprintf(ethaddr, "%pM", rom_enetaddr) ;
-		debug("### Setting environment from EEPROM MAC address = \"%s\"\n",
-		      ethaddr);
-		setenv("ethaddr", ethaddr);
+		debug("### Setting environment from EEPROM MAC address = "
+			"\"%pM\"\n",
+			env_enetaddr);
+		eth_setenv_enetaddr("ethaddr", rom_enetaddr);
 	}
 }
 
diff --git a/board/davinci/common/misc.h b/board/davinci/common/misc.h
index 329c369..a6ac3b9 100644
--- a/board/davinci/common/misc.h
+++ b/board/davinci/common/misc.h
@@ -46,7 +46,7 @@
 			  }
 
 int dvevm_read_mac_address(uint8_t *buf);
-void dv_configure_mac_address(uint8_t *rom_enetaddr);
+void davinci_sync_env_enetaddr(uint8_t *rom_enetaddr);
 int davinci_configure_pin_mux(const struct pinmux_config *pins, int n_pins);
 int davinci_configure_pin_mux_items(const struct pinmux_resource *item,
 				    int n_items);
diff --git a/board/davinci/da8xxevm/da830evm.c b/board/davinci/da8xxevm/da830evm.c
index 6baa860..8a9f988 100644
--- a/board/davinci/da8xxevm/da830evm.c
+++ b/board/davinci/da8xxevm/da830evm.c
@@ -196,19 +196,17 @@
 {
 	u_int8_t mac_addr[6];
 	u_int8_t switch_start_cmd[2] = { 0x01, 0x23 };
+	struct eth_device *dev;
 
 	/* Read Ethernet MAC address from EEPROM */
 	if (dvevm_read_mac_address(mac_addr))
 		/* set address env if not already set */
-		dv_configure_mac_address(mac_addr);
+		davinci_sync_env_enetaddr(mac_addr);
 
 	/* read the address back from env */
 	if (!eth_getenv_enetaddr("ethaddr", mac_addr))
 		return -1;
 
-	/* provide the resulting addr to the driver */
-	davinci_eth_set_mac_addr(mac_addr);
-
 	/* enable the Ethernet switch in the 3 port PHY */
 	if (i2c_write(PHY_SW_I2C_ADDR, 0, 0,
 			switch_start_cmd, sizeof(switch_start_cmd))) {
@@ -222,6 +220,12 @@
 		return -1;
 	}
 
+	dev = eth_get_dev();
+
+	/* provide the resulting addr to the driver */
+	memcpy(dev->enetaddr, mac_addr, 6);
+	dev->write_hwaddr(dev);
+
 	return 0;
 }
 #endif /* CONFIG_DRIVER_TI_EMAC */
diff --git a/board/davinci/dm365evm/dm365evm.c b/board/davinci/dm365evm/dm365evm.c
index 290eb99..85dbe2a 100644
--- a/board/davinci/dm365evm/dm365evm.c
+++ b/board/davinci/dm365evm/dm365evm.c
@@ -68,7 +68,7 @@
 
 	/* Read Ethernet MAC address from EEPROM */
 	if (dvevm_read_mac_address(eeprom_enetaddr))
-		dv_configure_mac_address(eeprom_enetaddr);
+		davinci_sync_env_enetaddr(eeprom_enetaddr);
 
 	davinci_emac_initialize();
 
diff --git a/board/davinci/dvevm/dvevm.c b/board/davinci/dvevm/dvevm.c
index 98937a9..073c21a 100644
--- a/board/davinci/dvevm/dvevm.c
+++ b/board/davinci/dvevm/dvevm.c
@@ -71,7 +71,7 @@
 
 	/* Read Ethernet MAC address from EEPROM if available. */
 	if (dvevm_read_mac_address(eeprom_enetaddr))
-		dv_configure_mac_address(eeprom_enetaddr);
+		davinci_sync_env_enetaddr(eeprom_enetaddr);
 
 	i2c_read(0x39, 0x00, 1, &video_mode, 1);
 
diff --git a/board/davinci/sffsdr/sffsdr.c b/board/davinci/sffsdr/sffsdr.c
index c24b9e1..657cf2b 100644
--- a/board/davinci/sffsdr/sffsdr.c
+++ b/board/davinci/sffsdr/sffsdr.c
@@ -141,7 +141,7 @@
 
 	/* Read Ethernet MAC address from EEPROM if available. */
 	if (sffsdr_read_mac_address(eeprom_enetaddr))
-		dv_configure_mac_address(eeprom_enetaddr);
+		davinci_sync_env_enetaddr(eeprom_enetaddr);
 
 	return(0);
 }
diff --git a/board/davinci/sonata/sonata.c b/board/davinci/sonata/sonata.c
index 817970a..1dc42c4 100644
--- a/board/davinci/sonata/sonata.c
+++ b/board/davinci/sonata/sonata.c
@@ -70,7 +70,7 @@
 
 	/* Read Ethernet MAC address from EEPROM if available. */
 	if (dvevm_read_mac_address(eeprom_enetaddr))
-		dv_configure_mac_address(eeprom_enetaddr);
+		davinci_sync_env_enetaddr(eeprom_enetaddr);
 
 	return(0);
 }
diff --git a/board/pdm360ng/pdm360ng.c b/board/pdm360ng/pdm360ng.c
index e8714e3..2082ad4 100644
--- a/board/pdm360ng/pdm360ng.c
+++ b/board/pdm360ng/pdm360ng.c
@@ -515,6 +515,46 @@
 };
 #endif
 
+#if defined(CONFIG_VIDEO)
+/*
+ * EDID block has been generated using Phoenix EDID Designer 1.3.
+ * This tool creates a text file containing:
+ *
+ * EDID BYTES:
+ * 0x   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ *     ------------------------------------------------
+ * 00 | 00 FF FF FF FF FF FF 00 42 C9 34 12 01 00 00 00
+ * 10 | 0A 0C 01 03 80 98 5B 78 CA 7E 50 A0 58 4E 96 25
+ * 20 | 1E 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01
+ * 30 | 01 01 01 01 01 01 80 0C 20 00 31 E0 2D 10 2A 80
+ * 40 | 12 08 30 E4 10 00 00 18 00 00 00 FD 00 38 3C 1F
+ * 50 | 3C 04 0A 20 20 20 20 20 20 20 00 00 00 FF 00 50
+ * 60 | 4D 30 37 30 57 4C 33 0A 0A 0A 0A 0A 00 00 00 FF
+ * 70 | 00 41 30 30 30 30 30 30 30 30 30 30 30 31 00 D4
+ *
+ * Then this data has been manually converted to the char
+ * array below.
+ */
+static unsigned char edid_buf[128] = {
+	0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+	0x42, 0xC9, 0x34, 0x12, 0x01, 0x00, 0x00, 0x00,
+	0x0A, 0x0C, 0x01, 0x03, 0x80, 0x98, 0x5B, 0x78,
+	0xCA, 0x7E, 0x50, 0xA0, 0x58, 0x4E, 0x96, 0x25,
+	0x1E, 0x50, 0x54, 0x00, 0x00, 0x00, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x0C,
+	0x20, 0x00, 0x31, 0xE0, 0x2D, 0x10, 0x2A, 0x80,
+	0x12, 0x08, 0x30, 0xE4, 0x10, 0x00, 0x00, 0x18,
+	0x00, 0x00, 0x00, 0xFD, 0x00, 0x38, 0x3C, 0x1F,
+	0x3C, 0x04, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x20, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x50,
+	0x4D, 0x30, 0x37, 0x30, 0x57, 0x4C, 0x33, 0x0A,
+	0x0A, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+	0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x00, 0xD4,
+};
+#endif
+
 void ft_board_setup(void *blob, bd_t *bd)
 {
 	u32 val[8];
@@ -525,6 +565,9 @@
 #ifdef CONFIG_FDT_FIXUP_PARTITIONS
 	fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
 #endif
+#if defined(CONFIG_VIDEO)
+	fdt_add_edid(blob, "fsl,mpc5121-diu", edid_buf);
+#endif
 
 	/* Fixup NOR FLASH mapping */
 	val[i++] = 0;				/* chip select number */
diff --git a/board/ppmc7xx/ppmc7xx.c b/board/ppmc7xx/ppmc7xx.c
index 0cad897..5e7427f 100644
--- a/board/ppmc7xx/ppmc7xx.c
+++ b/board/ppmc7xx/ppmc7xx.c
@@ -19,8 +19,7 @@
 
 
 /* Function prototypes */
-extern void unlock_ram_in_cache( void );
-extern void _start_warm(void);
+extern void _start(void);
 
 
 /*
@@ -97,8 +96,8 @@
 	icache_disable();
 	dcache_disable();
 
-	/* Jump to warm start (in RAM) */
-	_start_warm();
+	/* Jump to cold reset point (in RAM) */
+	_start();
 
 	/* Should never get here */
 	while(1);
diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c
index 838f131..744384c 100644
--- a/board/xilinx/microblaze-generic/microblaze-generic.c
+++ b/board/xilinx/microblaze-generic/microblaze-generic.c
@@ -27,6 +27,7 @@
 
 #include <common.h>
 #include <config.h>
+#include <netdev.h>
 #include <asm/microblaze_intc.h>
 #include <asm/asm.h>
 
@@ -66,3 +67,15 @@
 	return 0;
 }
 #endif
+
+int board_eth_init(bd_t *bis)
+{
+	/*
+	 * This board either has PCI NICs or uses the CPU's TSECs
+	 * pci_eth_init() will return 0 if no NICs found, so in that case
+	 * returning -1 will force cpu_eth_init() to be called.
+	 */
+#ifdef CONFIG_XILINX_EMACLITE
+	return xilinx_emaclite_initialize(bis, XILINX_EMACLITE_BASEADDR);
+#endif
+}
diff --git a/boards.cfg b/boards.cfg
index 38fa570..132d178 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -91,6 +91,7 @@
 DB64460		powerpc	74xx_7xx 	db64460		Marvell
 aria		powerpc	mpc512x		-		davedenx
 PATI		powerpc	mpc5xx		pati		mpl
+a4m072		powerpc	mpc5xxx		a4m072
 BC3450		powerpc	mpc5xxx		bc3450
 canmb		powerpc	mpc5xxx
 cm5200		powerpc	mpc5xxx
diff --git a/common/cmd_display.c b/common/cmd_display.c
index 6c11aa6..d5d5d8c 100644
--- a/common/cmd_display.c
+++ b/common/cmd_display.c
@@ -23,40 +23,32 @@
 
 #include <common.h>
 #include <command.h>
+#include <led-display.h>
 
 #undef DEBUG_DISP
 
-#define DISP_SIZE	8
-#define CWORD_CLEAR	0x80
-#define CLEAR_DELAY	(110 * 2)
-
 int do_display (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	int i;
-	int pos;
 
 	/* Clear display */
-	*((volatile char*)(CONFIG_SYS_DISP_CWORD)) = CWORD_CLEAR;
-	udelay(1000 * CLEAR_DELAY);
+	display_set(DISPLAY_CLEAR | DISPLAY_HOME);
 
 	if (argc < 2)
 		return (0);
 
-	for (pos = 0, i = 1; i < argc && pos < DISP_SIZE; i++) {
-		char *p = argv[i], c;
+	for (i = 1; i < argc; i++) {
+		char *p = argv[i];
 
-		if (i > 1) {
-			*((volatile uchar *) (CONFIG_SYS_DISP_CHR_RAM + pos++)) = ' ';
-#ifdef DEBUG_DISP
-			putc(' ');
-#endif
+		if (i > 1) { /* Insert a space between strings */
+			display_putc(' ');
 		}
 
-		while ((c = *p++) != '\0' && pos < DISP_SIZE) {
-			*((volatile uchar *) (CONFIG_SYS_DISP_CHR_RAM + pos++)) = c;
+		while ((*p)) {
 #ifdef DEBUG_DISP
-			putc(c);
+			putc(*p);
 #endif
+			display_putc(*p++);
 		}
 	}
 
diff --git a/common/cmd_flash.c b/common/cmd_flash.c
index 2a02eb9..4493948 100644
--- a/common/cmd_flash.c
+++ b/common/cmd_flash.c
@@ -31,7 +31,7 @@
 #include <dataflash.h>
 #endif
 
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
 #include <jffs2/jffs2.h>
 
 /* partition handling routines */
@@ -327,7 +327,7 @@
 	flash_info_t *info;
 	ulong bank, addr_first, addr_last;
 	int n, sect_first, sect_last;
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
 	struct mtd_device *dev;
 	struct part_info *part;
 	u8 dev_type, dev_num, pnum;
@@ -357,7 +357,7 @@
 		return rcode;
 	}
 
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
 	/* erase <part-id> - erase partition */
 	if ((argc == 2) && (mtd_id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) {
 		mtdparts_init();
@@ -463,7 +463,7 @@
 #if !defined(CONFIG_SYS_NO_FLASH) || defined(CONFIG_HAS_DATAFLASH)
 	ulong addr_first, addr_last;
 #endif
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
 	struct mtd_device *dev;
 	struct part_info *part;
 	u8 dev_type, dev_num, pnum;
@@ -553,7 +553,7 @@
 		return rcode;
 	}
 
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
 	/* protect on/off <part-id> */
 	if ((argc == 3) && (mtd_id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) {
 		mtdparts_init();
@@ -681,7 +681,7 @@
 
 
 /**************************************************/
-#if defined(CONFIG_CMD_JFFS2) && defined(CONFIG_CMD_MTDPARTS)
+#if defined(CONFIG_CMD_MTDPARTS)
 # define TMP_ERASE	"erase <part-id>\n    - erase partition\n"
 # define TMP_PROT_ON	"protect on <part-id>\n    - protect partition\n"
 # define TMP_PROT_OFF	"protect off <part-id>\n    - make partition writable\n"
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index 44834ea..f7a442a 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -337,6 +337,10 @@
 		ngood++;
 		addr1 += size;
 		addr2 += size;
+
+		/* reset watchdog from time to time */
+		if ((count % (64 << 10)) == 0)
+			WATCHDOG_RESET();
 	}
 
 	printf("Total of %ld %s%s were the same\n",
@@ -447,6 +451,10 @@
 			*((u_char *)dest) = *((u_char *)addr);
 		addr += size;
 		dest += size;
+
+		/* reset watchdog from time to time */
+		if ((count % (64 << 10)) == 0)
+			WATCHDOG_RESET();
 	}
 	return 0;
 }
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index ceec5a9..5481c88 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -15,6 +15,9 @@
  *   Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4
  *   kernel tree.
  *
+ * (C) Copyright 2008
+ * Harald Welte, OpenMoko, Inc., Harald Welte <laforge@openmoko.org>
+ *
  *   $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
  *   Copyright 2002 SYSGO Real-Time Solutions GmbH
  *
@@ -286,6 +289,29 @@
 	index_partitions();
 }
 
+
+/**
+ * Produce a mtd_info given a type and num.
+ *
+ * @param type mtd type
+ * @param num mtd number
+ * @param mtd a pointer to an mtd_info instance (output)
+ * @return 0 if device is valid, 1 otherwise
+ */
+static int get_mtd_info(u8 type, u8 num, struct mtd_info **mtd)
+{
+	char mtd_dev[16];
+
+	sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(type), num);
+	*mtd = get_mtd_device_nm(mtd_dev);
+	if (IS_ERR(*mtd)) {
+		printf("Device %s not found!\n", mtd_dev);
+		return 1;
+	}
+
+	return 0;
+}
+
 /**
  * Performs sanity check for supplied flash partition.
  * Table of existing MTD flash devices is searched and partition device
@@ -297,17 +323,12 @@
  */
 static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
 {
-	struct mtd_info *mtd;
-	char mtd_dev[16];
+	struct mtd_info *mtd = NULL;
 	int i, j;
 	ulong start;
 
-	sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(id->type), id->num);
-	mtd = get_mtd_device_nm(mtd_dev);
-	if (IS_ERR(mtd)) {
-		printf("Partition %s not found on device %s!\n", part->name, mtd_dev);
+	if (get_mtd_info(id->type, id->num, &mtd))
 		return 1;
-	}
 
 	part->sector_size = mtd->erasesize;
 
@@ -684,20 +705,17 @@
 /**
  * Check device number to be within valid range for given device type.
  *
- * @param dev device to validate
+ * @param type mtd type
+ * @param num mtd number
+ * @param size a pointer to the size of the mtd device (output)
  * @return 0 if device is valid, 1 otherwise
  */
 int mtd_device_validate(u8 type, u8 num, u32 *size)
 {
-	struct mtd_info *mtd;
-	char mtd_dev[16];
+	struct mtd_info *mtd = NULL;
 
-	sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(type), num);
-	mtd = get_mtd_device_nm(mtd_dev);
-	if (IS_ERR(mtd)) {
-		printf("Device %s not found!\n", mtd_dev);
+	if (get_mtd_info(type, num, &mtd))
 		return 1;
-	}
 
 	*size = mtd->size;
 
@@ -1200,38 +1218,93 @@
 	return ret;
 }
 
+#if defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES)
 /**
- * Format and print out a partition list for each device from global device
- * list.
+ * Get the net size (w/o bad blocks) of the given partition.
+ *
+ * @param mtd the mtd info
+ * @param part the partition
+ * @return the calculated net size of this partition
  */
-static void list_partitions(void)
+static uint64_t net_part_size(struct mtd_info *mtd, struct part_info *part)
+{
+	uint64_t i, net_size = 0;
+
+	if (!mtd->block_isbad)
+		return part->size;
+
+	for (i = 0; i < part->size; i += mtd->erasesize) {
+		if (!mtd->block_isbad(mtd, part->offset + i))
+			net_size += mtd->erasesize;
+	}
+
+	return net_size;
+}
+#endif
+
+static void print_partition_table(void)
 {
 	struct list_head *dentry, *pentry;
 	struct part_info *part;
 	struct mtd_device *dev;
 	int part_num;
 
-	debug("\n---list_partitions---\n");
 	list_for_each(dentry, &devices) {
 		dev = list_entry(dentry, struct mtd_device, link);
+		/* list partitions for given device */
+		part_num = 0;
+#if defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES)
+		struct mtd_info *mtd;
+
+		if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+			return;
+
+		printf("\ndevice %s%d <%s>, # parts = %d\n",
+				MTD_DEV_TYPE(dev->id->type), dev->id->num,
+				dev->id->mtd_id, dev->num_parts);
+		printf(" #: name\t\tsize\t\tnet size\toffset\t\tmask_flags\n");
+
+		list_for_each(pentry, &dev->parts) {
+			u32 net_size;
+			char *size_note;
+
+			part = list_entry(pentry, struct part_info, link);
+			net_size = net_part_size(mtd, part);
+			size_note = part->size == net_size ? " " : " (!)";
+			printf("%2d: %-20s0x%08x\t0x%08x%s\t0x%08x\t%d\n",
+					part_num, part->name, part->size,
+					net_size, size_note, part->offset,
+					part->mask_flags);
+#else /* !defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
 		printf("\ndevice %s%d <%s>, # parts = %d\n",
 				MTD_DEV_TYPE(dev->id->type), dev->id->num,
 				dev->id->mtd_id, dev->num_parts);
 		printf(" #: name\t\tsize\t\toffset\t\tmask_flags\n");
 
-		/* list partitions for given device */
-		part_num = 0;
 		list_for_each(pentry, &dev->parts) {
 			part = list_entry(pentry, struct part_info, link);
 			printf("%2d: %-20s0x%08x\t0x%08x\t%d\n",
 					part_num, part->name, part->size,
 					part->offset, part->mask_flags);
-
+#endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
 			part_num++;
 		}
 	}
+
 	if (list_empty(&devices))
 		printf("no partitions defined\n");
+}
+
+/**
+ * Format and print out a partition list for each device from global device
+ * list.
+ */
+static void list_partitions(void)
+{
+	struct part_info *part;
+
+	debug("\n---list_partitions---\n");
+	print_partition_table();
 
 	/* current_mtd_dev is not NULL only when we have non empty device list */
 	if (current_mtd_dev) {
@@ -1355,6 +1428,101 @@
 	return 1;
 }
 
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+/**
+ * Increase the size of the given partition so that it's net size is at least
+ * as large as the size member and such that the next partition would start on a
+ * good block if it were adjacent to this partition.
+ *
+ * @param mtd the mtd device
+ * @param part the partition
+ * @param next_offset pointer to the offset of the next partition after this
+ *                    partition's size has been modified (output)
+ */
+static void spread_partition(struct mtd_info *mtd, struct part_info *part,
+			     uint64_t *next_offset)
+{
+	uint64_t net_size, padding_size = 0;
+	int truncated;
+
+	mtd_get_len_incl_bad(mtd, part->offset, part->size, &net_size,
+			     &truncated);
+
+	/*
+	 * Absorb bad blocks immediately following this
+	 * partition also into the partition, such that
+	 * the next partition starts with a good block.
+	 */
+	if (!truncated) {
+		mtd_get_len_incl_bad(mtd, part->offset + net_size,
+				     mtd->erasesize, &padding_size, &truncated);
+		if (truncated)
+			padding_size = 0;
+		else
+			padding_size -= mtd->erasesize;
+	}
+
+	if (truncated) {
+		printf("truncated partition %s to %lld bytes\n", part->name,
+		       (uint64_t) net_size + padding_size);
+	}
+
+	part->size = net_size + padding_size;
+	*next_offset = part->offset + part->size;
+}
+
+/**
+ * Adjust all of the partition sizes, such that all partitions are at least
+ * as big as their mtdparts environment variable sizes and they each start
+ * on a good block.
+ *
+ * @return 0 on success, 1 otherwise
+ */
+static int spread_partitions(void)
+{
+	struct list_head *dentry, *pentry;
+	struct mtd_device *dev;
+	struct part_info *part;
+	struct mtd_info *mtd;
+	int part_num;
+	uint64_t cur_offs;
+
+	list_for_each(dentry, &devices) {
+		dev = list_entry(dentry, struct mtd_device, link);
+
+		if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+			return 1;
+
+		part_num = 0;
+		cur_offs = 0;
+		list_for_each(pentry, &dev->parts) {
+			part = list_entry(pentry, struct part_info, link);
+
+			debug("spread_partitions: device = %s%d, partition %d ="
+				" (%s) 0x%08x@0x%08x\n",
+				MTD_DEV_TYPE(dev->id->type), dev->id->num,
+				part_num, part->name, part->size,
+				part->offset);
+
+			if (cur_offs > part->offset)
+				part->offset = cur_offs;
+
+			spread_partition(mtd, part, &cur_offs);
+
+			part_num++;
+		}
+	}
+
+	index_partitions();
+
+	if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+		printf("generated mtdparts too long, reseting to null\n");
+		return 1;
+	}
+	return 0;
+}
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+
 /**
  * Accept character string describing mtd partitions and call device_parse()
  * for each entry. Add created devices to the global devices list.
@@ -1782,9 +1950,13 @@
 	}
 
 	/* mtdparts add <mtd-dev> <size>[@<offset>] <name> [ro] */
-	if (((argc == 5) || (argc == 6)) && (strcmp(argv[1], "add") == 0)) {
+	if (((argc == 5) || (argc == 6)) && (strncmp(argv[1], "add", 3) == 0)) {
 #define PART_ADD_DESC_MAXLEN 64
 		char tmpbuf[PART_ADD_DESC_MAXLEN];
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+		struct mtd_info *mtd;
+		uint64_t next_offset;
+#endif
 		u8 type, num, len;
 		struct mtd_device *dev;
 		struct mtd_device *dev_tmp;
@@ -1819,15 +1991,25 @@
 		debug("+ %s\t%d\t%s\n", MTD_DEV_TYPE(dev->id->type),
 				dev->id->num, dev->id->mtd_id);
 
-		if ((dev_tmp = device_find(dev->id->type, dev->id->num)) == NULL) {
+		p = list_entry(dev->parts.next, struct part_info, link);
+
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+		if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+			return 1;
+
+		if (!strcmp(&argv[1][3], ".spread")) {
+			spread_partition(mtd, p, &next_offset);
+			debug("increased %s to %d bytes\n", p->name, p->size);
+		}
+#endif
+
+		dev_tmp = device_find(dev->id->type, dev->id->num);
+		if (dev_tmp == NULL) {
 			device_add(dev);
-		} else {
+		} else if (part_add(dev_tmp, p) != 0) {
 			/* merge new partition with existing ones*/
-			p = list_entry(dev->parts.next, struct part_info, link);
-			if (part_add(dev_tmp, p) != 0) {
-				device_del(dev);
-				return 1;
-			}
+			device_del(dev);
+			return 1;
 		}
 
 		if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
@@ -1845,6 +2027,11 @@
 		return delete_partition(argv[2]);
 	}
 
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+	if ((argc == 2) && (strcmp(argv[1], "spread") == 0))
+		return spread_partitions();
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
+
 	return cmd_usage(cmdtp);
 }
 
@@ -1867,8 +2054,20 @@
 	"    - delete partition (e.g. part-id = nand0,1)\n"
 	"mtdparts add <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
 	"    - add partition\n"
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+	"mtdparts add.spread <mtd-dev> <size>[@<offset>] [<name>] [ro]\n"
+	"    - add partition, padding size by skipping bad blocks\n"
+#endif
 	"mtdparts default\n"
-	"    - reset partition table to defaults\n\n"
+	"    - reset partition table to defaults\n"
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+	"mtdparts spread\n"
+	"    - adjust the sizes of the partitions so they are\n"
+	"      at least as big as the mtdparts variable specifies\n"
+	"      and they each start on a good block\n\n"
+#else
+	"\n"
+#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
 	"-----\n\n"
 	"this command uses three environment variables:\n\n"
 	"'partition' - keeps current partition identifier\n\n"
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 3f1d077..8a81237 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -10,6 +10,13 @@
  * (C) Copyright 2006-2007 OpenMoko, Inc.
  * Added 16-bit nand support
  * (C) 2004 Texas Instruments
+ *
+ * Copyright 2010 Freescale Semiconductor
+ * The portions of this file whose copyright is held by Freescale and which
+ * are not considered a derived work of GPL v2-only code may be distributed
+ * and/or modified under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
  */
 
 #include <common.h>
@@ -30,10 +37,16 @@
 		      u8 *part_num, struct part_info **part);
 #endif
 
-static int nand_dump(nand_info_t *nand, ulong off, int only_oob)
+static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
 {
 	int i;
 	u_char *datbuf, *oobbuf, *p;
+	static loff_t last;
+
+	if (repeat)
+		off = last + nand->writesize;
+
+	last = off;
 
 	datbuf = malloc(nand->writesize + nand->oobsize);
 	oobbuf = malloc(nand->oobsize);
@@ -85,74 +98,132 @@
 
 /* ------------------------------------------------------------------------- */
 
-static inline int str2long(char *p, ulong *num)
+static int set_dev(int dev)
+{
+	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+	    !nand_info[dev].name) {
+		puts("No such device\n");
+		return -1;
+	}
+
+	if (nand_curr_device == dev)
+		return 0;
+
+	printf("Device %d: %s", dev, nand_info[dev].name);
+	puts("... is now current device\n");
+	nand_curr_device = dev;
+
+#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
+	board_nand_select_device(nand_info[dev].priv, dev);
+#endif
+
+	return 0;
+}
+
+static inline int str2off(const char *p, loff_t *num)
+{
+	char *endptr;
+
+	*num = simple_strtoull(p, &endptr, 16);
+	return *p != '\0' && *endptr == '\0';
+}
+
+static inline int str2long(const char *p, ulong *num)
 {
 	char *endptr;
 
 	*num = simple_strtoul(p, &endptr, 16);
-	return (*p != '\0' && *endptr == '\0') ? 1 : 0;
+	return *p != '\0' && *endptr == '\0';
 }
 
-static int
-arg_off_size(int argc, char * const argv[], nand_info_t *nand, ulong *off, size_t *size)
+static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)
 {
-	int idx = nand_curr_device;
-#if defined(CONFIG_CMD_MTDPARTS)
+#ifdef CONFIG_CMD_MTDPARTS
 	struct mtd_device *dev;
 	struct part_info *part;
 	u8 pnum;
+	int ret;
 
-	if (argc >= 1 && !(str2long(argv[0], off))) {
-		if ((mtdparts_init() == 0) &&
-		    (find_dev_and_part(argv[0], &dev, &pnum, &part) == 0)) {
-			if (dev->id->type != MTD_DEV_TYPE_NAND) {
-				puts("not a NAND device\n");
-				return -1;
-			}
-			*off = part->offset;
-			if (argc >= 2) {
-				if (!(str2long(argv[1], (ulong *)size))) {
-					printf("'%s' is not a number\n", argv[1]);
-					return -1;
-				}
-				if (*size > part->size)
-					*size = part->size;
-			} else {
-				*size = part->size;
-			}
-			idx = dev->id->num;
-			*nand = nand_info[idx];
-			goto out;
-		}
+	ret = mtdparts_init();
+	if (ret)
+		return ret;
+
+	ret = find_dev_and_part(partname, &dev, &pnum, &part);
+	if (ret)
+		return ret;
+
+	if (dev->id->type != MTD_DEV_TYPE_NAND) {
+		puts("not a NAND device\n");
+		return -1;
 	}
-#endif
 
-	if (argc >= 1) {
-		if (!(str2long(argv[0], off))) {
-			printf("'%s' is not a number\n", argv[0]);
-			return -1;
-		}
-	} else {
+	*off = part->offset;
+	*size = part->size;
+	*idx = dev->id->num;
+
+	ret = set_dev(*idx);
+	if (ret)
+		return ret;
+
+	return 0;
+#else
+	puts("offset is not a number\n");
+	return -1;
+#endif
+}
+
+static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)
+{
+	if (!str2off(arg, off))
+		return get_part(arg, idx, off, maxsize);
+
+	if (*off >= nand_info[*idx].size) {
+		puts("Offset exceeds device limit\n");
+		return -1;
+	}
+
+	*maxsize = nand_info[*idx].size - *off;
+	return 0;
+}
+
+static int arg_off_size(int argc, char *const argv[], int *idx,
+			loff_t *off, loff_t *size)
+{
+	int ret;
+	loff_t maxsize;
+
+	if (argc == 0) {
 		*off = 0;
+		*size = nand_info[*idx].size;
+		goto print;
 	}
 
-	if (argc >= 2) {
-		if (!(str2long(argv[1], (ulong *)size))) {
-			printf("'%s' is not a number\n", argv[1]);
-			return -1;
-		}
-	} else {
-		*size = nand->size - *off;
+	ret = arg_off(argv[0], idx, off, &maxsize);
+	if (ret)
+		return ret;
+
+	if (argc == 1) {
+		*size = maxsize;
+		goto print;
 	}
 
-#if defined(CONFIG_CMD_MTDPARTS)
-out:
-#endif
-	printf("device %d ", idx);
-	if (*size == nand->size)
+	if (!str2off(argv[1], size)) {
+		printf("'%s' is not a number\n", argv[1]);
+		return -1;
+	}
+
+	if (*size > maxsize) {
+		puts("Size exceeds partition or device limit\n");
+		return -1;
+	}
+
+print:
+	printf("device %d ", *idx);
+	if (*size == nand_info[*idx].size)
 		puts("whole chip\n");
 	else
-		printf("offset 0x%lx, size 0x%zx\n", *off, *size);
+		printf("offset 0x%llx, size 0x%llx\n",
+		       (unsigned long long)*off, (unsigned long long)*size);
 	return 0;
 }
 
@@ -200,14 +271,20 @@
 #ifdef CONFIG_ENV_OFFSET_OOB
 unsigned long nand_env_oob_offset;
 
-int do_nand_env_oob(cmd_tbl_t *cmdtp, nand_info_t *nand,
-		    int argc, char * const argv[])
+int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
 {
 	int ret;
 	uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
-
+	nand_info_t *nand = &nand_info[0];
 	char *cmd = argv[1];
 
+	if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
+		puts("no devices available\n");
+		return 1;
+	}
+
+	set_dev(0);
+
 	if (!strcmp(cmd, "get")) {
 		ret = get_nand_env_oob(nand, &nand_env_oob_offset);
 		if (ret)
@@ -215,16 +292,21 @@
 
 		printf("0x%08lx\n", nand_env_oob_offset);
 	} else if (!strcmp(cmd, "set")) {
-		ulong addr;
-		size_t dummy_size;
+		loff_t addr;
+		loff_t maxsize;
 		struct mtd_oob_ops ops;
+		int idx = 0;
 
 		if (argc < 3)
 			goto usage;
 
-		if (arg_off_size(argc - 2, argv + 2, nand, &addr,
-				 &dummy_size) < 0) {
-			printf("Offset or partition name expected\n");
+		if (arg_off(argv[2], &idx, &addr, &maxsize)) {
+			puts("Offset or partition name expected\n");
+			return 1;
+		}
+
+		if (idx != 0) {
+			puts("Partition not on first NAND device\n");
 			return 1;
 		}
 
@@ -264,8 +346,8 @@
 
 		if (addr != nand_env_oob_offset) {
 			printf("Verification of env offset in OOB failed: "
-			       "0x%08lx expected but got 0x%08lx\n",
-			       addr, nand_env_oob_offset);
+			       "0x%08llx expected but got 0x%08lx\n",
+			       (unsigned long long)addr, nand_env_oob_offset);
 			return 1;
 		}
 	} else {
@@ -293,9 +375,9 @@
 
 int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
-	int i, dev, ret = 0;
-	ulong addr, off;
-	size_t size;
+	int i, ret = 0;
+	ulong addr;
+	loff_t off, size;
 	char *cmd, *s;
 	nand_info_t *nand;
 #ifdef CONFIG_SYS_NAND_QUIET
@@ -304,6 +386,8 @@
 	int quiet = 0;
 #endif
 	const char *quiet_str = getenv("quiet");
+	int dev = nand_curr_device;
+	int repeat = flag & CMD_FLAG_REPEAT;
 
 	/* at least two arguments please */
 	if (argc < 2)
@@ -314,6 +398,10 @@
 
 	cmd = argv[1];
 
+	/* Only "dump" is repeatable. */
+	if (repeat && strcmp(cmd, "dump"))
+		return 0;
+
 	if (strcmp(cmd, "info") == 0) {
 
 		putc('\n');
@@ -325,68 +413,45 @@
 	}
 
 	if (strcmp(cmd, "device") == 0) {
-
 		if (argc < 3) {
 			putc('\n');
-			if ((nand_curr_device < 0) ||
-			    (nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE))
+			if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE)
 				puts("no devices available\n");
 			else
-				nand_print_info(nand_curr_device);
+				nand_print_info(dev);
 			return 0;
 		}
-		dev = (int)simple_strtoul(argv[2], NULL, 10);
-		if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) {
-			puts("No such device\n");
-			return 1;
-		}
-		printf("Device %d: %s", dev, nand_info[dev].name);
-		puts("... is now current device\n");
-		nand_curr_device = dev;
 
-#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
-		/*
-		 * Select the chip in the board/cpu specific driver
-		 */
-		board_nand_select_device(nand_info[dev].priv, dev);
-#endif
+		dev = (int)simple_strtoul(argv[2], NULL, 10);
+		set_dev(dev);
 
 		return 0;
 	}
 
-	if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
-	    strncmp(cmd, "dump", 4) != 0 &&
-	    strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
-	    strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
-	    strcmp(cmd, "biterr") != 0 &&
-	    strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0
-#ifdef CONFIG_ENV_OFFSET_OOB
-	    && strcmp(cmd, "env.oob") != 0
-#endif
-	    )
-		goto usage;
-
 #ifdef CONFIG_ENV_OFFSET_OOB
 	/* this command operates only on the first nand device */
-	if (strcmp(cmd, "env.oob") == 0) {
-		return do_nand_env_oob(cmdtp, &nand_info[0],
-				       argc - 1, argv + 1);
-	}
+	if (strcmp(cmd, "env.oob") == 0)
+		return do_nand_env_oob(cmdtp, argc - 1, argv + 1);
 #endif
 
-	/* the following commands operate on the current device */
-	if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
-	    !nand_info[nand_curr_device].name) {
+	/* The following commands operate on the current device, unless
+	 * overridden by a partition specifier.  Note that if somehow the
+	 * current device is invalid, it will have to be changed to a valid
+	 * one before these commands can run, even if a partition specifier
+	 * for another device is to be used.
+	 */
+	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+	    !nand_info[dev].name) {
 		puts("\nno devices available\n");
 		return 1;
 	}
-	nand = &nand_info[nand_curr_device];
+	nand = &nand_info[dev];
 
 	if (strcmp(cmd, "bad") == 0) {
-		printf("\nDevice %d bad blocks:\n", nand_curr_device);
+		printf("\nDevice %d bad blocks:\n", dev);
 		for (off = 0; off < nand->size; off += nand->erasesize)
 			if (nand_block_isbad(nand, off))
-				printf("  %08lx\n", off);
+				printf("  %08llx\n", (unsigned long long)off);
 		return 0;
 	}
 
@@ -395,23 +460,52 @@
 	 *   0    1     2       3    4
 	 *   nand erase [clean] [off size]
 	 */
-	if (strcmp(cmd, "erase") == 0 || strcmp(cmd, "scrub") == 0) {
+	if (strncmp(cmd, "erase", 5) == 0 || strncmp(cmd, "scrub", 5) == 0) {
 		nand_erase_options_t opts;
 		/* "clean" at index 2 means request to write cleanmarker */
 		int clean = argc > 2 && !strcmp("clean", argv[2]);
 		int o = clean ? 3 : 2;
-		int scrub = !strcmp(cmd, "scrub");
+		int scrub = !strncmp(cmd, "scrub", 5);
+		int part = 0;
+		int chip = 0;
+		int spread = 0;
+		int args = 2;
 
-		printf("\nNAND %s: ", scrub ? "scrub" : "erase");
+		if (cmd[5] != 0) {
+			if (!strcmp(&cmd[5], ".spread")) {
+				spread = 1;
+			} else if (!strcmp(&cmd[5], ".part")) {
+				part = 1;
+				args = 1;
+			} else if (!strcmp(&cmd[5], ".chip")) {
+				chip = 1;
+				args = 0;
+			} else {
+				goto usage;
+			}
+		}
+
+		/*
+		 * Don't allow missing arguments to cause full chip/partition
+		 * erases -- easy to do accidentally, e.g. with a misspelled
+		 * variable name.
+		 */
+		if (argc != o + args)
+			goto usage;
+
+		printf("\nNAND %s: ", cmd);
 		/* skip first two or three arguments, look for offset and size */
-		if (arg_off_size(argc - o, argv + o, nand, &off, &size) != 0)
+		if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0)
 			return 1;
 
+		nand = &nand_info[dev];
+
 		memset(&opts, 0, sizeof(opts));
 		opts.offset = off;
 		opts.length = size;
 		opts.jffs2  = clean;
 		opts.quiet  = quiet;
+		opts.spread = spread;
 
 		if (scrub) {
 			puts("Warning: "
@@ -449,19 +543,14 @@
 		if (argc < 3)
 			goto usage;
 
-		s = strchr(cmd, '.');
 		off = (int)simple_strtoul(argv[2], NULL, 16);
-
-		if (s != NULL && strcmp(s, ".oob") == 0)
-			ret = nand_dump(nand, off, 1);
-		else
-			ret = nand_dump(nand, off, 0);
+		ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
 
 		return ret == 0 ? 1 : 0;
-
 	}
 
 	if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
+		size_t rwsize;
 		int read;
 
 		if (argc < 4)
@@ -471,23 +560,26 @@
 
 		read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
 		printf("\nNAND %s: ", read ? "read" : "write");
-		if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
+		if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0)
 			return 1;
 
+		nand = &nand_info[dev];
+		rwsize = size;
+
 		s = strchr(cmd, '.');
 		if (!s || !strcmp(s, ".jffs2") ||
 		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
 			if (read)
-				ret = nand_read_skip_bad(nand, off, &size,
+				ret = nand_read_skip_bad(nand, off, &rwsize,
 							 (u_char *)addr);
 			else
-				ret = nand_write_skip_bad(nand, off, &size,
+				ret = nand_write_skip_bad(nand, off, &rwsize,
 							  (u_char *)addr);
 		} else if (!strcmp(s, ".oob")) {
 			/* out-of-band data */
 			mtd_oob_ops_t ops = {
 				.oobbuf = (u8 *)addr,
-				.ooblen = size,
+				.ooblen = rwsize,
 				.mode = MTD_OOB_RAW
 			};
 
@@ -500,7 +592,7 @@
 			return 1;
 		}
 
-		printf(" %zu bytes %s: %s\n", size,
+		printf(" %zu bytes %s: %s\n", rwsize,
 		       read ? "read" : "written", ret ? "ERROR" : "OK");
 
 		return ret == 0 ? 0 : 1;
@@ -564,7 +656,7 @@
 		if (arg_off_size(argc - 2, argv + 2, nand, &off, &size) < 0)
 			return 1;
 
-		if (!nand_unlock(nand, off, size)) {
+		if (!nand_unlock(&nand_info[dev], off, size)) {
 			puts("NAND flash successfully unlocked\n");
 		} else {
 			puts("Error unlocking NAND flash, "
@@ -588,11 +680,16 @@
 	"nand write - addr off|partition size\n"
 	"    read/write 'size' bytes starting at offset 'off'\n"
 	"    to/from memory address 'addr', skipping bad blocks.\n"
-	"nand erase [clean] [off size] - erase 'size' bytes from\n"
-	"    offset 'off' (entire device if not specified)\n"
+	"nand erase[.spread] [clean] [off [size]] - erase 'size' bytes "
+	"from offset 'off'\n"
+	"    With '.spread', erase enough for given file size, otherwise,\n"
+	"    'size' includes skipped bad blocks.\n"
+	"nand erase.part [clean] partition - erase entire mtd partition'\n"
+	"nand erase.chip [clean] - erase entire chip'\n"
 	"nand bad - show bad blocks\n"
 	"nand dump[.oob] off - dump page\n"
-	"nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
+	"nand scrub off size | scrub.part partition | scrub.chip\n"
+	"    really clean NAND erasing bad blocks (UNSAFE)\n"
 	"nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
 	"nand biterr off - make a bit error at offset (UNSAFE)"
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
diff --git a/common/cmd_net.c b/common/cmd_net.c
index 3ffb9df..44d17db 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -54,6 +54,7 @@
 	"[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 
+#ifdef CONFIG_CMD_RARP
 int do_rarpb (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	return netboot_common (RARP, cmdtp, argc, argv);
@@ -64,6 +65,7 @@
 	"boot image via network using RARP/TFTP protocol",
 	"[loadAddress] [[hostIPaddr:]bootfilename]"
 );
+#endif
 
 #if defined(CONFIG_CMD_DHCP)
 int do_dhcp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
diff --git a/common/cmd_tsi148.c b/common/cmd_tsi148.c
index 1e83c88..6dc9dab 100644
--- a/common/cmd_tsi148.c
+++ b/common/cmd_tsi148.c
@@ -419,7 +419,7 @@
 	if (argc > 5)
 		vam = simple_strtoul(argv[5], NULL, 16);
 	if (argc > 6)
-		vdw = simple_strtoul(argv[7], NULL, 16);
+		vdw = simple_strtoul(argv[6], NULL, 16);
 
 	switch (cmd) {
 	case 'c':
@@ -465,7 +465,7 @@
 }
 
 U_BOOT_CMD(
-	tsi148,	8,	1,	do_tsi148,
+	tsi148,	7,	1,	do_tsi148,
 	"initialize and configure Turndra Tsi148\n",
 	"init\n"
 	"    - initialize tsi148\n"
diff --git a/common/env_common.c b/common/env_common.c
index 88f068c..5acda4d 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -237,8 +237,8 @@
 		set_default_env(NULL);
 #else
 		show_boot_progress (-60);
-#endif
 		set_default_env("!bad CRC");
+#endif
 	} else {
 		env_relocate_spec ();
 	}
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 0ed6e77..b8a3dc9 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -667,6 +667,16 @@
 }
 #endif
 
+int fdt_increase_size(void *fdt, int add_len)
+{
+	int newlen;
+
+	newlen = fdt_totalsize(fdt) + add_len;
+
+	/* Open in place with a new len */
+	return fdt_open_into(fdt, fdt, newlen);
+}
+
 #ifdef CONFIG_FDT_FIXUP_PARTITIONS
 #include <jffs2/load_kernel.h>
 #include <mtd_node.h>
@@ -701,16 +711,6 @@
 	return 0;
 }
 
-int fdt_increase_size(void *fdt, int add_len)
-{
-	int newlen;
-
-	newlen = fdt_totalsize(fdt) + add_len;
-
-	/* Open in place with a new len */
-	return fdt_open_into(fdt, fdt, newlen);
-}
-
 int fdt_del_partitions(void *blob, int parent_offset)
 {
 	const void *prop;
@@ -1189,3 +1189,32 @@
 
 	return phandle + 1;
 }
+
+#if defined(CONFIG_VIDEO)
+int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf)
+{
+	int noff;
+	int ret;
+
+	noff = fdt_node_offset_by_compatible(blob, -1, compat);
+	if (noff != -FDT_ERR_NOTFOUND) {
+		debug("%s: %s\n", fdt_get_name(blob, noff, 0), compat);
+add_edid:
+		ret = fdt_setprop(blob, noff, "edid", edid_buf, 128);
+		if (ret == -FDT_ERR_NOSPACE) {
+			ret = fdt_increase_size(blob, 512);
+			if (!ret)
+				goto add_edid;
+			else
+				goto err_size;
+		} else if (ret < 0) {
+			printf("Can't add property: %s\n", fdt_strerror(ret));
+			return ret;
+		}
+	}
+	return 0;
+err_size:
+	printf("Can't increase blob size: %s\n", fdt_strerror(ret));
+	return ret;
+}
+#endif
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 76949b8..613c4f0 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -204,6 +204,22 @@
 	return 1;
 }
 
+static unsigned int usb_get_max_lun(struct us_data *us)
+{
+	int len;
+	unsigned char result;
+	len = usb_control_msg(us->pusb_dev,
+			      usb_rcvctrlpipe(us->pusb_dev, 0),
+			      US_BBB_GET_MAX_LUN,
+			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+			      0, us->ifnum,
+			      &result, sizeof(result),
+			      USB_CNTL_TIMEOUT * 5);
+	USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
+			len, (int) result);
+	return (len > 0) ? result : 0;
+}
+
 /*******************************************************************************
  * scan the usb and reports device info
  * to the user if mode = 1
@@ -241,13 +257,22 @@
 			break; /* no more devices avaiable */
 
 		if (usb_storage_probe(dev, 0, &usb_stor[usb_max_devs])) {
-			/* ok, it is a storage devices
-			 * get info and fill it in
+			/* OK, it's a storage device.  Iterate over its LUNs
+			 * and populate `usb_dev_desc'.
 			 */
-			if (usb_stor_get_info(dev, &usb_stor[usb_max_devs],
-						&usb_dev_desc[usb_max_devs]) == 1)
+			int lun, max_lun, start = usb_max_devs;
+
+			max_lun = usb_get_max_lun(&usb_stor[usb_max_devs]);
+			for (lun = 0;
+			     lun <= max_lun && usb_max_devs < USB_MAX_STOR_DEV;
+			     lun++) {
+				usb_dev_desc[usb_max_devs].lun = lun;
+				if (usb_stor_get_info(dev, &usb_stor[start],
+						      &usb_dev_desc[usb_max_devs]) == 1) {
 				usb_max_devs++;
 		}
+			}
+		}
 		/* if storage device */
 		if (usb_max_devs == USB_MAX_STOR_DEV) {
 			printf("max USB Storage Device reached: %d stopping\n",
@@ -882,6 +907,7 @@
 	do {
 		memset(&srb->cmd[0], 0, 12);
 		srb->cmd[0] = SCSI_INQUIRY;
+		srb->cmd[1] = srb->lun << 5;
 		srb->cmd[4] = 36;
 		srb->datalen = 36;
 		srb->cmdlen = 12;
@@ -905,6 +931,7 @@
 	ptr = (char *)srb->pdata;
 	memset(&srb->cmd[0], 0, 12);
 	srb->cmd[0] = SCSI_REQ_SENSE;
+	srb->cmd[1] = srb->lun << 5;
 	srb->cmd[4] = 18;
 	srb->datalen = 18;
 	srb->pdata = &srb->sense_buf[0];
@@ -924,6 +951,7 @@
 	do {
 		memset(&srb->cmd[0], 0, 12);
 		srb->cmd[0] = SCSI_TST_U_RDY;
+		srb->cmd[1] = srb->lun << 5;
 		srb->datalen = 0;
 		srb->cmdlen = 12;
 		if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
@@ -943,6 +971,7 @@
 	do {
 		memset(&srb->cmd[0], 0, 12);
 		srb->cmd[0] = SCSI_RD_CAPAC;
+		srb->cmd[1] = srb->lun << 5;
 		srb->datalen = 8;
 		srb->cmdlen = 12;
 		if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD)
@@ -957,6 +986,7 @@
 {
 	memset(&srb->cmd[0], 0, 12);
 	srb->cmd[0] = SCSI_READ10;
+	srb->cmd[1] = srb->lun << 5;
 	srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
 	srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
 	srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
@@ -973,6 +1003,7 @@
 {
 	memset(&srb->cmd[0], 0, 12);
 	srb->cmd[0] = SCSI_WRITE10;
+	srb->cmd[1] = srb->lun << 5;
 	srb->cmd[2] = ((unsigned char) (start >> 24)) & 0xff;
 	srb->cmd[3] = ((unsigned char) (start >> 16)) & 0xff;
 	srb->cmd[4] = ((unsigned char) (start >> 8)) & 0xff;
diff --git a/doc/README.LED_display b/doc/README.LED_display
new file mode 100644
index 0000000..521746e
--- /dev/null
+++ b/doc/README.LED_display
@@ -0,0 +1,27 @@
+LED display internal API
+=======================================
+
+This README describes the LED display API.
+
+The API is defined by the include file include/led-display.h
+
+The first step in to define CONFIG_CMD_DISPLAY in the board config file.
+Then you need to provide the following functions to access LED display:
+
+void display_set(int cmd);
+
+This function should control the state of the LED display. Argument is
+an ORed combination of the following values:
+ DISPLAY_CLEAR	-- clear the display
+ DISPLAY_HOME	-- set the position to the beginning of display
+ DISPLAY_MARK	-- enable mark (decimal point), if implemented
+
+int display_putc(char c);
+
+This function should display it's parameter on the LED display in the
+current position. Returns the displayed character on success or -1 in
+case of failure.
+
+With this functions defined 'display' command will display it's
+arguments on the LED display (or clear the display if called without
+arguments).
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 4f15db9..5d668f8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -33,6 +33,7 @@
 COBJS-$(CONFIG_STATUS_LED) += status_led.o
 COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
 COBJS-$(CONFIG_FSL_PMIC) += fsl_pmic.o
+COBJS-$(CONFIG_PDSP188x) += pdsp188x.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/misc/pdsp188x.c b/drivers/misc/pdsp188x.c
new file mode 100644
index 0000000..656b6ee
--- /dev/null
+++ b/drivers/misc/pdsp188x.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010 Sergey Poselenov, Emcraft Systems, <sposelenov@emcraft.com>
+ * Copyright 2010 Ilya Yanok, Emcraft Systems, <yanok@emcraft.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <led-display.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CMD_DISPLAY
+#define CWORD_CLEAR	0x80
+#define CLEAR_DELAY	(110 * 2)
+#define DISPLAY_SIZE	8
+
+static int pos; /* Current display position */
+
+/* Handle different display commands */
+void display_set(int cmd)
+{
+	if (cmd & DISPLAY_CLEAR) {
+		out_8((unsigned char *)CONFIG_SYS_DISP_CWORD, CWORD_CLEAR);
+		udelay(1000 * CLEAR_DELAY);
+	}
+
+	if (cmd & DISPLAY_HOME) {
+		pos = 0;
+	}
+}
+
+/*
+ * Display a character at the current display position.
+ * Characters beyond the display size are ignored.
+ */
+int display_putc(char c)
+{
+	if (pos >= DISPLAY_SIZE)
+		return -1;
+
+	out_8((unsigned char *)CONFIG_SYS_DISP_CHR_RAM + pos++, c);
+
+	return c;
+}
+#endif
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 02dd27f..798902f 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -2033,7 +2033,7 @@
 			printf ("## Unknown FLASH on Bank %d "
 				"- Size = 0x%08lx = %ld MB\n",
 				i+1, flash_info[i].size,
-				flash_info[i].size << 20);
+				flash_info[i].size >> 20);
 #endif /* CONFIG_SYS_FLASH_QUIET_TEST */
 		}
 #ifdef CONFIG_SYS_FLASH_PROTECTION
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 6eb52ed..a195dda 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -142,3 +142,47 @@
 	c = --mtd->usecount;
 	BUG_ON(c < 0);
 }
+
+#if defined(CONFIG_CMD_MTDPARTS_SPREAD)
+/**
+ * mtd_get_len_incl_bad
+ *
+ * Check if length including bad blocks fits into device.
+ *
+ * @param mtd an MTD device
+ * @param offset offset in flash
+ * @param length image length
+ * @return image length including bad blocks in *len_incl_bad and whether or not
+ *         the length returned was truncated in *truncated
+ */
+void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
+			  const uint64_t length, uint64_t *len_incl_bad,
+			  int *truncated)
+{
+	*truncated = 0;
+	*len_incl_bad = 0;
+
+	if (!mtd->block_isbad) {
+		*len_incl_bad = length;
+		return;
+	}
+
+	uint64_t len_excl_bad = 0;
+	uint64_t block_len;
+
+	while (len_excl_bad < length) {
+		if (offset >= mtd->size) {
+			*truncated = 1;
+			return;
+		}
+
+		block_len = mtd->erasesize - (offset & (mtd->erasesize - 1));
+
+		if (!mtd->block_isbad(mtd, offset & ~(mtd->erasesize - 1)))
+			len_excl_bad += block_len;
+
+		*len_incl_bad += block_len;
+		offset       += block_len;
+	}
+}
+#endif /* defined(CONFIG_CMD_MTDPARTS_SPREAD) */
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index e2e43ea..f647e43 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -230,18 +230,6 @@
 	part->master->sync(part->master);
 }
 
-static int part_suspend(struct mtd_info *mtd)
-{
-	struct mtd_part *part = PART(mtd);
-	return part->master->suspend(part->master);
-}
-
-static void part_resume(struct mtd_info *mtd)
-{
-	struct mtd_part *part = PART(mtd);
-	part->master->resume(part->master);
-}
-
 static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_part *part = PART(mtd);
@@ -339,10 +327,6 @@
 		slave->mtd.get_fact_prot_info = part_get_fact_prot_info;
 	if (master->sync)
 		slave->mtd.sync = part_sync;
-	if (!partno && master->suspend && master->resume) {
-			slave->mtd.suspend = part_suspend;
-			slave->mtd.resume = part_resume;
-	}
 	if (master->lock)
 		slave->mtd.lock = part_lock;
 	if (master->unlock)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 7d17846..21cc5a3 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -32,30 +32,6 @@
  *
  */
 
-/* XXX U-BOOT XXX */
-#if 0
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/compatmac.h>
-#include <linux/interrupt.h>
-#include <linux/bitops.h>
-#include <linux/leds.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_MTD_PARTITIONS
-#include <linux/mtd/partitions.h>
-#endif
-
-#endif
-
 #include <common.h>
 
 #define ENOTSUPP	524	/* Operation is not supported */
@@ -75,10 +51,6 @@
 #include <asm/io.h>
 #include <asm/errno.h>
 
-#ifdef CONFIG_JFFS2_NAND
-#include <jffs2/jffs2.h>
-#endif
-
 /*
  * CONFIG_SYS_NAND_RESET_CNT is used as a timeout mechanism when resetting
  * a flash.  NAND flash is initialized prior to interrupts so standard timers
@@ -143,44 +115,17 @@
 
 static int nand_wait(struct mtd_info *mtd, struct nand_chip *this);
 
-/*
- * For devices which display every fart in the system on a separate LED. Is
- * compiled away when LED support is disabled.
- */
-/* XXX U-BOOT XXX */
-#if 0
-DEFINE_LED_TRIGGER(nand_led_trigger);
-#endif
-
 /**
  * nand_release_device - [GENERIC] release chip
  * @mtd:	MTD device structure
  *
  * Deselect, release chip lock and wake up anyone waiting on the device
  */
-/* XXX U-BOOT XXX */
-#if 0
-static void nand_release_device(struct mtd_info *mtd)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	/* De-select the NAND device */
-	chip->select_chip(mtd, -1);
-
-	/* Release the controller and the chip */
-	spin_lock(&chip->controller->lock);
-	chip->controller->active = NULL;
-	chip->state = FL_READY;
-	wake_up(&chip->controller->wq);
-	spin_unlock(&chip->controller->lock);
-}
-#else
 static void nand_release_device (struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
 	this->select_chip(mtd, -1);	/* De-select the NAND device */
 }
-#endif
 
 /**
  * nand_read_byte - [DEFAULT] read one byte from the chip
@@ -490,24 +435,6 @@
  * Wait for the ready pin, after a command
  * The timeout is catched later.
  */
-/* XXX U-BOOT XXX */
-#if 0
-void nand_wait_ready(struct mtd_info *mtd)
-{
-	struct nand_chip *chip = mtd->priv;
-	unsigned long timeo = jiffies + 2;
-
-	led_trigger_event(nand_led_trigger, LED_FULL);
-	/* wait until command is processed or timeout occures */
-	do {
-		if (chip->dev_ready(mtd))
-			break;
-		touch_softlockup_watchdog();
-	} while (time_before(jiffies, timeo));
-	led_trigger_event(nand_led_trigger, LED_OFF);
-}
-EXPORT_SYMBOL_GPL(nand_wait_ready);
-#else
 void nand_wait_ready(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
@@ -522,7 +449,6 @@
 				break;
 	}
 }
-#endif
 
 /**
  * nand_command - [DEFAULT] Send command to NAND device
@@ -759,45 +685,11 @@
  *
  * Get the device and lock it for exclusive access
  */
-/* XXX U-BOOT XXX */
-#if 0
-static int
-nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
-{
-	spinlock_t *lock = &chip->controller->lock;
-	wait_queue_head_t *wq = &chip->controller->wq;
-	DECLARE_WAITQUEUE(wait, current);
- retry:
-	spin_lock(lock);
-
-	/* Hardware controller shared among independend devices */
-	/* Hardware controller shared among independend devices */
-	if (!chip->controller->active)
-		chip->controller->active = chip;
-
-	if (chip->controller->active == chip && chip->state == FL_READY) {
-		chip->state = new_state;
-		spin_unlock(lock);
-		return 0;
-	}
-	if (new_state == FL_PM_SUSPENDED) {
-		spin_unlock(lock);
-		return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
-	}
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(wq, &wait);
-	spin_unlock(lock);
-	schedule();
-	remove_wait_queue(wq, &wait);
-	goto retry;
-}
-#else
 static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)
 {
 	this->state = new_state;
 	return 0;
 }
-#endif
 
 /**
  * nand_wait - [DEFAULT]  wait until the command is done
@@ -808,46 +700,6 @@
  * Erase can take up to 400ms and program up to 20ms according to
  * general NAND and SmartMedia specs
  */
-/* XXX U-BOOT XXX */
-#if 0
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
-{
-
-	unsigned long timeo = jiffies;
-	int status, state = chip->state;
-
-	if (state == FL_ERASING)
-		timeo += (HZ * 400) / 1000;
-	else
-		timeo += (HZ * 20) / 1000;
-
-	led_trigger_event(nand_led_trigger, LED_FULL);
-
-	/* Apply this short delay always to ensure that we do wait tWB in
-	 * any case on any machine. */
-	ndelay(100);
-
-	if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
-		chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
-	else
-		chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
-
-	while (time_before(jiffies, timeo)) {
-		if (chip->dev_ready) {
-			if (chip->dev_ready(mtd))
-				break;
-		} else {
-			if (chip->read_byte(mtd) & NAND_STATUS_READY)
-				break;
-		}
-		cond_resched();
-	}
-	led_trigger_event(nand_led_trigger, LED_OFF);
-
-	status = (int)chip->read_byte(mtd);
-	return status;
-}
-#else
 static int nand_wait(struct mtd_info *mtd, struct nand_chip *this)
 {
 	unsigned long	timeo;
@@ -886,7 +738,6 @@
 
 	return this->read_byte(mtd);
 }
-#endif
 
 /**
  * nand_read_page_raw - [Intern] read raw page data without ecc
@@ -2001,13 +1852,6 @@
 	if (!writelen)
 		return 0;
 
-	/* reject writes, which are not page aligned */
-	if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
-		printk(KERN_NOTICE "nand_write: "
-		       "Attempt to write not page aligned data\n");
-		return -EINVAL;
-	}
-
 	column = to & (mtd->writesize - 1);
 	subpage = column || (writelen & (mtd->writesize - 1));
 
@@ -2523,32 +2367,6 @@
 	return chip->block_markbad(mtd, ofs);
 }
 
-/**
- * nand_suspend - [MTD Interface] Suspend the NAND flash
- * @mtd:	MTD device structure
- */
-static int nand_suspend(struct mtd_info *mtd)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
-}
-
-/**
- * nand_resume - [MTD Interface] Resume the NAND flash
- * @mtd:	MTD device structure
- */
-static void nand_resume(struct mtd_info *mtd)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	if (chip->state == FL_PM_SUSPENDED)
-		nand_release_device(mtd);
-	else
-		printk(KERN_ERR "nand_resume() called for a chip which is not "
-		       "in suspended state\n");
-}
-
 /*
  * Set default functions
  */
@@ -2584,17 +2402,8 @@
 		chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
 	if (!chip->scan_bbt)
 		chip->scan_bbt = nand_default_bbt;
-
-	if (!chip->controller) {
+	if (!chip->controller)
 		chip->controller = &chip->hwcontrol;
-
-		/* XXX U-BOOT XXX */
-#if 0
-		spin_lock_init(&chip->controller->lock);
-		init_waitqueue_head(&chip->controller->wq);
-#endif
-	}
-
 }
 
 /*
@@ -3028,8 +2837,6 @@
 	mtd->sync = nand_sync;
 	mtd->lock = NULL;
 	mtd->unlock = NULL;
-	mtd->suspend = nand_suspend;
-	mtd->resume = nand_resume;
 	mtd->block_isbad = nand_block_isbad;
 	mtd->block_markbad = nand_block_markbad;
 
@@ -3043,16 +2850,6 @@
 	return 0;
 }
 
-/* module_text_address() isn't exported, and it's mostly a pointless
-   test if this is a module _anyway_ -- they'd have to try _really_ hard
-   to call us from in-kernel code if the core NAND support is modular. */
-#ifdef MODULE
-#define caller_is_module() (1)
-#else
-#define caller_is_module() \
-	module_text_address((unsigned long)__builtin_return_address(0))
-#endif
-
 /**
  * nand_scan - [NAND Interface] Scan for the NAND device
  * @mtd:	MTD device structure
@@ -3069,15 +2866,6 @@
 {
 	int ret;
 
-	/* Many callers got this wrong, so check for it for a while... */
-	/* XXX U-BOOT XXX */
-#if 0
-	if (!mtd->owner && caller_is_module()) {
-		printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
-		BUG();
-	}
-#endif
-
 	ret = nand_scan_ident(mtd, maxchips);
 	if (!ret)
 		ret = nand_scan_tail(mtd);
@@ -3096,40 +2884,9 @@
 	/* Deregister partitions */
 	del_mtd_partitions(mtd);
 #endif
-	/* Deregister the device */
-	/* XXX U-BOOT XXX */
-#if 0
-	del_mtd_device(mtd);
-#endif
 
 	/* Free bad block table memory */
 	kfree(chip->bbt);
 	if (!(chip->options & NAND_OWN_BUFFERS))
 		kfree(chip->buffers);
 }
-
-/* XXX U-BOOT XXX */
-#if 0
-EXPORT_SYMBOL_GPL(nand_scan);
-EXPORT_SYMBOL_GPL(nand_scan_ident);
-EXPORT_SYMBOL_GPL(nand_scan_tail);
-EXPORT_SYMBOL_GPL(nand_release);
-
-static int __init nand_base_init(void)
-{
-	led_trigger_register_simple("nand-disk", &nand_led_trigger);
-	return 0;
-}
-
-static void __exit nand_base_exit(void)
-{
-	led_trigger_unregister_simple(nand_led_trigger);
-}
-
-module_init(nand_base_init);
-module_exit(nand_base_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Generic NAND flash driver code");
-#endif
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 2fe68ab..521ddde 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -58,19 +58,6 @@
 
 #include <asm/errno.h>
 
-/* XXX U-BOOT XXX */
-#if 0
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/compatmac.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/vmalloc.h>
-#endif
-
 /**
  * check_pattern - [GENERIC] check if a pattern is in the buffer
  * @buf:	the buffer to search
@@ -1231,9 +1218,3 @@
 	}
 	return 1;
 }
-
-/* XXX U-BOOT XXX */
-#if 0
-EXPORT_SYMBOL(nand_scan_bbt);
-EXPORT_SYMBOL(nand_default_bbt);
-#endif
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 463f9cb..52bc916 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -37,14 +37,6 @@
 
 #include <common.h>
 
-/* XXX U-BOOT XXX */
-#if 0
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mtd/nand_ecc.h>
-#endif
-
 #include <asm/errno.h>
 #include <linux/mtd/mtd.h>
 
@@ -140,10 +132,6 @@
 
 	return 0;
 }
-/* XXX U-BOOT XXX */
-#if 0
-EXPORT_SYMBOL(nand_calculate_ecc);
-#endif
 #endif /* CONFIG_NAND_SPL */
 
 static inline int countbits(uint32_t byte)
@@ -212,8 +200,3 @@
 
 	return -EBADMSG;
 }
-
-/* XXX U-BOOT XXX */
-#if 0
-EXPORT_SYMBOL(nand_correct_data);
-#endif
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 29c42f7..22c7411 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -28,6 +28,12 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  *
+ * Copyright 2010 Freescale Semiconductor
+ * The portions of this file whose copyright is held by Freescale and which
+ * are not considered a derived work of GPL v2-only code may be distributed
+ * and/or modified under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
  */
 
 #include <common.h>
@@ -69,7 +75,7 @@
 {
 	struct jffs2_unknown_node cleanmarker;
 	erase_info_t erase;
-	ulong erase_length;
+	unsigned long erase_length, erased_length; /* in blocks */
 	int bbtest = 1;
 	int result;
 	int percent_complete = -1;
@@ -78,13 +84,19 @@
 	struct mtd_oob_ops oob_opts;
 	struct nand_chip *chip = meminfo->priv;
 
+	if ((opts->offset & (meminfo->writesize - 1)) != 0) {
+		printf("Attempt to erase non page aligned data\n");
+		return -1;
+	}
+
 	memset(&erase, 0, sizeof(erase));
 	memset(&oob_opts, 0, sizeof(oob_opts));
 
 	erase.mtd = meminfo;
 	erase.len  = meminfo->erasesize;
 	erase.addr = opts->offset;
-	erase_length = opts->length;
+	erase_length = lldiv(opts->length + meminfo->erasesize - 1,
+			     meminfo->erasesize);
 
 	cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
 	cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
@@ -108,15 +120,8 @@
 		priv_nand->bbt = NULL;
 	}
 
-	if (erase_length < meminfo->erasesize) {
-		printf("Warning: Erase size 0x%08lx smaller than one "	\
-		       "erase block 0x%08x\n",erase_length, meminfo->erasesize);
-		printf("         Erasing 0x%08x instead\n", meminfo->erasesize);
-		erase_length = meminfo->erasesize;
-	}
-
-	for (;
-	     erase.addr < opts->offset + erase_length;
+	for (erased_length = 0;
+	     erased_length < erase_length;
 	     erase.addr += meminfo->erasesize) {
 
 		WATCHDOG_RESET ();
@@ -129,6 +134,10 @@
 					       "0x%08llx                 "
 					       "                         \n",
 					       erase.addr);
+
+				if (!opts->spread)
+					erased_length++;
+
 				continue;
 
 			} else if (ret < 0) {
@@ -139,6 +148,8 @@
 			}
 		}
 
+		erased_length++;
+
 		result = meminfo->erase(meminfo, &erase);
 		if (result != 0) {
 			printf("\n%s: MTD Erase failure: %d\n",
@@ -165,9 +176,7 @@
 		}
 
 		if (!opts->quiet) {
-			unsigned long long n =(unsigned long long)
-				(erase.addr + meminfo->erasesize - opts->offset)
-				* 100;
+			unsigned long long n = erased_length * 100ULL;
 			int percent;
 
 			do_div(n, erase_length);
@@ -202,41 +211,6 @@
 	return 0;
 }
 
-/* XXX U-BOOT XXX */
-#if 0
-
-#define MAX_PAGE_SIZE	2048
-#define MAX_OOB_SIZE	64
-
-/*
- * buffer array used for writing data
- */
-static unsigned char data_buf[MAX_PAGE_SIZE];
-static unsigned char oob_buf[MAX_OOB_SIZE];
-
-/* OOB layouts to pass into the kernel as default */
-static struct nand_ecclayout none_ecclayout = {
-	.useecc = MTD_NANDECC_OFF,
-};
-
-static struct nand_ecclayout jffs2_ecclayout = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 0, 1, 2, 3, 6, 7 }
-};
-
-static struct nand_ecclayout yaffs_ecclayout = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = { 8, 9, 10, 13, 14, 15}
-};
-
-static struct nand_ecclayout autoplace_ecclayout = {
-	.useecc = MTD_NANDECC_AUTOPLACE
-};
-#endif
-
-/* XXX U-BOOT XXX */
 #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 
 /******************************************************************************
@@ -423,36 +397,43 @@
 #endif
 
 /**
- * get_len_incl_bad
+ * check_skip_len
  *
- * Check if length including bad blocks fits into device.
+ * Check if there are any bad blocks, and whether length including bad
+ * blocks fits into device
  *
  * @param nand NAND device
  * @param offset offset in flash
  * @param length image length
- * @return image length including bad blocks
+ * @return 0 if the image fits and there are no bad blocks
+ *         1 if the image fits, but there are bad blocks
+ *        -1 if the image does not fit
  */
-static size_t get_len_incl_bad (nand_info_t *nand, loff_t offset,
-				const size_t length)
+static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length)
 {
-	size_t len_incl_bad = 0;
 	size_t len_excl_bad = 0;
-	size_t block_len;
+	int ret = 0;
 
 	while (len_excl_bad < length) {
-		block_len = nand->erasesize - (offset & (nand->erasesize - 1));
-
-		if (!nand_block_isbad (nand, offset & ~(nand->erasesize - 1)))
-			len_excl_bad += block_len;
-
-		len_incl_bad += block_len;
-		offset       += block_len;
+		size_t block_len, block_off;
+		loff_t block_start;
 
 		if (offset >= nand->size)
-			break;
+			return -1;
+
+		block_start = offset & ~(loff_t)(nand->erasesize - 1);
+		block_off = offset & (nand->erasesize - 1);
+		block_len = nand->erasesize - block_off;
+
+		if (!nand_block_isbad(nand, block_start))
+			len_excl_bad += block_len;
+		else
+			ret = 1;
+
+		offset += block_len;
 	}
 
-	return len_incl_bad;
+	return ret;
 }
 
 /**
@@ -474,29 +455,41 @@
 {
 	int rval;
 	size_t left_to_write = *length;
-	size_t len_incl_bad;
 	u_char *p_buffer = buffer;
+	int need_skip;
 
-	/* Reject writes, which are not page aligned */
-	if ((offset & (nand->writesize - 1)) != 0 ||
-	    (*length & (nand->writesize - 1)) != 0) {
+	/*
+	 * nand_write() handles unaligned, partial page writes.
+	 *
+	 * We allow length to be unaligned, for convenience in
+	 * using the $filesize variable.
+	 *
+	 * However, starting at an unaligned offset makes the
+	 * semantics of bad block skipping ambiguous (really,
+	 * you should only start a block skipping access at a
+	 * partition boundary).  So don't try to handle that.
+	 */
+	if ((offset & (nand->writesize - 1)) != 0) {
 		printf ("Attempt to write non page aligned data\n");
+		*length = 0;
 		return -EINVAL;
 	}
 
-	len_incl_bad = get_len_incl_bad (nand, offset, *length);
-
-	if ((offset + len_incl_bad) > nand->size) {
+	need_skip = check_skip_len(nand, offset, *length);
+	if (need_skip < 0) {
 		printf ("Attempt to write outside the flash area\n");
+		*length = 0;
 		return -EINVAL;
 	}
 
-	if (len_incl_bad == *length) {
+	if (!need_skip) {
 		rval = nand_write (nand, offset, length, buffer);
-		if (rval != 0)
-			printf ("NAND write to offset %llx failed %d\n",
-				offset, rval);
+		if (rval == 0)
+			return 0;
 
+		*length = 0;
+		printf ("NAND write to offset %llx failed %d\n",
+			offset, rval);
 		return rval;
 	}
 
@@ -553,20 +546,28 @@
 {
 	int rval;
 	size_t left_to_read = *length;
-	size_t len_incl_bad;
 	u_char *p_buffer = buffer;
+	int need_skip;
 
-	len_incl_bad = get_len_incl_bad (nand, offset, *length);
-
-	if ((offset + len_incl_bad) > nand->size) {
-		printf ("Attempt to read outside the flash area\n");
+	if ((offset & (nand->writesize - 1)) != 0) {
+		printf ("Attempt to read non page aligned data\n");
+		*length = 0;
 		return -EINVAL;
 	}
 
-	if (len_incl_bad == *length) {
+	need_skip = check_skip_len(nand, offset, *length);
+	if (need_skip < 0) {
+		printf ("Attempt to read outside the flash area\n");
+		*length = 0;
+		return -EINVAL;
+	}
+
+	if (!need_skip) {
 		rval = nand_read (nand, offset, length, buffer);
 		if (!rval || rval == -EUCLEAN)
 			return 0;
+
+		*length = 0;
 		printf ("NAND read from offset %llx failed %d\n",
 			offset, rval);
 		return rval;
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index f9273ab..24e02c2 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -2213,6 +2213,7 @@
 }
 
 static const struct onenand_manufacturers onenand_manuf_ids[] = {
+	{ONENAND_MFR_NUMONYX, "Numonyx"},
 	{ONENAND_MFR_SAMSUNG, "Samsung"},
 };
 
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index ea875dc..b4ba1dd 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -2,6 +2,8 @@
  * SPI flash interface
  *
  * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
+ *
  * Licensed under the GPL-2 or later.
  */
 
@@ -96,13 +98,68 @@
 	return ret;
 }
 
+/*
+ * The following table holds all device probe functions
+ *
+ * shift:  number of continuation bytes before the ID
+ * idcode: the expected IDCODE or 0xff for non JEDEC devices
+ * probe:  the function to call
+ *
+ * Non JEDEC devices should be ordered in the table such that
+ * the probe functions with best detection algorithms come first.
+ *
+ * Several matching entries are permitted, they will be tried
+ * in sequence until a probe function returns non NULL.
+ *
+ * IDCODE_CONT_LEN may be redefined if a device needs to declare a
+ * larger "shift" value.  IDCODE_PART_LEN generally shouldn't be
+ * changed.  This is the max number of bytes probe functions may
+ * examine when looking up part-specific identification info.
+ *
+ * Probe functions will be given the idcode buffer starting at their
+ * manu id byte (the "idcode" in the table below).  In other words,
+ * all of the continuation bytes will be skipped (the "shift" below).
+ */
+#define IDCODE_CONT_LEN 0
+#define IDCODE_PART_LEN 5
+static const struct {
+	const u8 shift;
+	const u8 idcode;
+	struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
+} flashes[] = {
+	/* Keep it sorted by define name */
+#ifdef CONFIG_SPI_FLASH_ATMEL
+	{ 0, 0x1f, spi_flash_probe_atmel, },
+#endif
+#ifdef CONFIG_SPI_FLASH_MACRONIX
+	{ 0, 0xc2, spi_flash_probe_macronix, },
+#endif
+#ifdef CONFIG_SPI_FLASH_SPANSION
+	{ 0, 0x01, spi_flash_probe_spansion, },
+#endif
+#ifdef CONFIG_SPI_FLASH_SST
+	{ 0, 0xbf, spi_flash_probe_sst, },
+#endif
+#ifdef CONFIG_SPI_FLASH_STMICRO
+	{ 0, 0x20, spi_flash_probe_stmicro, },
+#endif
+#ifdef CONFIG_SPI_FLASH_WINBOND
+	{ 0, 0xef, spi_flash_probe_winbond, },
+#endif
+	/* Keep it sorted by best detection */
+#ifdef CONFIG_SPI_FLASH_STMICRO
+	{ 0, 0xff, spi_flash_probe_stmicro, },
+#endif
+};
+#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
+
 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int spi_mode)
 {
 	struct spi_slave *spi;
-	struct spi_flash *flash;
-	int ret;
-	u8 idcode[5];
+	struct spi_flash *flash = NULL;
+	int ret, i, shift;
+	u8 idcode[IDCODE_LEN], *idp;
 
 	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
 	if (!spi) {
@@ -117,53 +174,34 @@
 	}
 
 	/* Read the ID codes */
-	ret = spi_flash_cmd(spi, CMD_READ_ID, &idcode, sizeof(idcode));
+	ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
 	if (ret)
 		goto err_read_id;
 
-	debug("SF: Got idcode %02x %02x %02x %02x %02x\n", idcode[0],
-			idcode[1], idcode[2], idcode[3], idcode[4]);
+#ifdef DEBUG
+	printf("SF: Got idcodes\n");
+	print_buffer(0, idcode, 1, sizeof(idcode), 0);
+#endif
 
-	switch (idcode[0]) {
-#ifdef CONFIG_SPI_FLASH_SPANSION
-	case 0x01:
-		flash = spi_flash_probe_spansion(spi, idcode);
-		break;
-#endif
-#ifdef CONFIG_SPI_FLASH_ATMEL
-	case 0x1F:
-		flash = spi_flash_probe_atmel(spi, idcode);
-		break;
-#endif
-#ifdef CONFIG_SPI_FLASH_MACRONIX
-	case 0xc2:
-		flash = spi_flash_probe_macronix(spi, idcode);
-		break;
-#endif
-#ifdef CONFIG_SPI_FLASH_WINBOND
-	case 0xef:
-		flash = spi_flash_probe_winbond(spi, idcode);
-		break;
-#endif
-#ifdef CONFIG_SPI_FLASH_STMICRO
-	case 0x20:
-	case 0xff: /* Let the stmicro func handle non-JEDEC ids */
-		flash = spi_flash_probe_stmicro(spi, idcode);
-		break;
-#endif
-#ifdef CONFIG_SPI_FLASH_SST
-	case 0xBF:
-		flash = spi_flash_probe_sst(spi, idcode);
-		break;
-#endif
-	default:
-		printf("SF: Unsupported manufacturer %02X\n", idcode[0]);
-		flash = NULL;
-		break;
-	}
+	/* count the number of continuation bytes */
+	for (shift = 0, idp = idcode;
+	     shift < IDCODE_CONT_LEN && *idp == 0x7f;
+	     ++shift, ++idp)
+		continue;
 
-	if (!flash)
+	/* search the table for matches in shift and id */
+	for (i = 0; i < ARRAY_SIZE(flashes); ++i)
+		if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
+			/* we have a match, call probe */
+			flash = flashes[i].probe(spi, idp);
+			if (flash)
+				break;
+		}
+
+	if (!flash) {
+		printf("SF: Unsupported manufacturer %02x\n", *idp);
 		goto err_manufacturer_probe;
+	}
 
 	spi_release_bus(spi);
 
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 218eeff..79eb66b 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -40,6 +40,7 @@
 COBJS-$(CONFIG_E1000) += e1000.o
 COBJS-$(CONFIG_EEPRO100) += eepro100.o
 COBJS-$(CONFIG_ENC28J60) += enc28j60.o
+COBJS-$(CONFIG_ENC28J60_LPC2292) += enc28j60_lpc2292.o
 COBJS-$(CONFIG_EP93XX) += ep93xx_eth.o
 COBJS-$(CONFIG_ETHOC) += ethoc.o
 COBJS-$(CONFIG_FEC_MXC) += fec_mxc.o
diff --git a/drivers/net/at91_emac.c b/drivers/net/at91_emac.c
index ca2b16b..4e5685c 100644
--- a/drivers/net/at91_emac.c
+++ b/drivers/net/at91_emac.c
@@ -220,7 +220,7 @@
 	at91emac_write(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMCR,
 		(BMCR_ANENABLE | BMCR_ANRESTART));
 
-	for (i = 0; i < 100000 / 100; i++) {
+	for (i = 0; i < 30000; i++) {
 		at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 			MII_BMSR, &status);
 		if (status & BMSR_ANEGCOMPLETE)
@@ -233,7 +233,7 @@
 	} else {
 		printf("%s: Autonegotiation timed out (status=0x%04x)\n",
 		       netdev->name, status);
-		return 1;
+		return -1;
 	}
 	return 0;
 }
@@ -252,7 +252,7 @@
 		MII_PHYSID1, &phy_id);
 	if (phy_id == 0xffff) {
 		printf("%s: No PHY present\n", netdev->name);
-		return 1;
+		return -1;
 	}
 
 	at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
@@ -261,7 +261,7 @@
 	if (!(status & BMSR_LSTATUS)) {
 		/* Try to re-negotiate if we don't have link already. */
 		if (at91emac_phy_reset(netdev))
-			return 2;
+			return -2;
 
 		for (i = 0; i < 100000 / 100; i++) {
 			at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
@@ -273,7 +273,7 @@
 	}
 	if (!(status & BMSR_LSTATUS)) {
 		VERBOSEP("%s: link down\n", netdev->name);
-		return 3;
+		return -3;
 	} else {
 		at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR,
 			MII_ADVERTISE, &adv);
@@ -298,7 +298,7 @@
 	at91emac_read(emac, CONFIG_DRIVER_AT91EMAC_PHYADDR, MII_BMSR, &stat1);
 
 	if (!(stat1 & BMSR_LSTATUS))	/* link status up? */
-		return 1;
+		return -1;
 
 	if (stat1 & BMSR_100FULL) {
 		/*set Emac for 100BaseTX and Full Duplex  */
@@ -333,7 +333,7 @@
 			&emac->cfg);
 		return 0;
 	}
-	return 1;
+	return 0;
 }
 
 static int at91emac_init(struct eth_device *netdev, bd_t *bd)
@@ -399,7 +399,7 @@
 		at91emac_UpdateLinkSpeed(emac);
 		return 0;
 	}
-	return 1;
+	return -1;
 }
 
 static void at91emac_halt(struct eth_device *netdev)
@@ -501,11 +501,11 @@
 		iobase = AT91_EMAC_BASE;
 	emac = malloc(sizeof(*emac)+512);
 	if (emac == NULL)
-		return 1;
+		return -1;
 	dev = malloc(sizeof(*dev));
 	if (dev == NULL) {
 		free(emac);
-		return 1;
+		return -1;
 	}
 	/* alignment as per Errata (64 bytes) is insufficient! */
 	emacfix = (emac_device *) (((unsigned long) emac + 0x1ff) & 0xFFFFFE00);
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 41a9910..e06896f 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -65,21 +65,6 @@
 	davinci_eth_mdio_enable();
 }
 
-static u_int8_t davinci_eth_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-/*
- * This function must be called before emac_open() if you want to override
- * the default mac address.
- */
-void davinci_eth_set_mac_addr(const u_int8_t *addr)
-{
-	int i;
-
-	for (i = 0; i < sizeof (davinci_eth_mac_addr); i++) {
-		davinci_eth_mac_addr[i] = addr[i];
-	}
-}
-
 /* EMAC Addresses */
 static volatile emac_regs	*adap_emac = (emac_regs *)EMAC_BASE_ADDR;
 static volatile ewrap_regs	*adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
@@ -100,6 +85,43 @@
 
 phy_t				phy;
 
+static int davinci_eth_set_mac_addr(struct eth_device *dev)
+{
+	unsigned long		mac_hi;
+	unsigned long		mac_lo;
+
+	/*
+	 * Set MAC Addresses & Init multicast Hash to 0 (disable any multicast
+	 * receive)
+	 *  Using channel 0 only - other channels are disabled
+	 *  */
+	writel(0, &adap_emac->MACINDEX);
+	mac_hi = (dev->enetaddr[3] << 24) |
+		 (dev->enetaddr[2] << 16) |
+		 (dev->enetaddr[1] << 8)  |
+		 (dev->enetaddr[0]);
+	mac_lo = (dev->enetaddr[5] << 8) |
+		 (dev->enetaddr[4]);
+
+	writel(mac_hi, &adap_emac->MACADDRHI);
+#if defined(DAVINCI_EMAC_VERSION2)
+	writel(mac_lo | EMAC_MAC_ADDR_IS_VALID | EMAC_MAC_ADDR_MATCH,
+	       &adap_emac->MACADDRLO);
+#else
+	writel(mac_lo, &adap_emac->MACADDRLO);
+#endif
+
+	writel(0, &adap_emac->MACHASH1);
+	writel(0, &adap_emac->MACHASH2);
+
+	/* Set source MAC address - REQUIRED */
+	writel(mac_hi, &adap_emac->MACSRCADDRHI);
+	writel(mac_lo, &adap_emac->MACSRCADDRLO);
+
+
+	return 0;
+}
+
 static void davinci_eth_mdio_enable(void)
 {
 	u_int32_t	clkdiv;
@@ -286,8 +308,6 @@
 	dv_reg_p		addr;
 	u_int32_t		clkdiv, cnt;
 	volatile emac_desc	*rx_desc;
-	unsigned long		mac_hi;
-	unsigned long		mac_lo;
 
 	debug_emac("+ emac_open\n");
 
@@ -311,30 +331,7 @@
 	writel(1, &adap_emac->TXCONTROL);
 	writel(1, &adap_emac->RXCONTROL);
 
-	/* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */
-	/* Using channel 0 only - other channels are disabled */
-	writel(0, &adap_emac->MACINDEX);
-	mac_hi = (davinci_eth_mac_addr[3] << 24) |
-		 (davinci_eth_mac_addr[2] << 16) |
-		 (davinci_eth_mac_addr[1] << 8)  |
-		 (davinci_eth_mac_addr[0]);
-	mac_lo = (davinci_eth_mac_addr[5] << 8) |
-		 (davinci_eth_mac_addr[4]);
-
-	writel(mac_hi, &adap_emac->MACADDRHI);
-#if defined(DAVINCI_EMAC_VERSION2)
-	writel(mac_lo | EMAC_MAC_ADDR_IS_VALID | EMAC_MAC_ADDR_MATCH,
-	       &adap_emac->MACADDRLO);
-#else
-	writel(mac_lo, &adap_emac->MACADDRLO);
-#endif
-
-	writel(0, &adap_emac->MACHASH1);
-	writel(0, &adap_emac->MACHASH2);
-
-	/* Set source MAC address - REQUIRED */
-	writel(mac_hi, &adap_emac->MACSRCADDRHI);
-	writel(mac_lo, &adap_emac->MACSRCADDRLO);
+	davinci_eth_set_mac_addr(dev);
 
 	/* Set DMA 8 TX / 8 RX Head pointers to 0 */
 	addr = &adap_emac->TX0HDP;
@@ -636,6 +633,7 @@
 	dev->halt = davinci_eth_close;
 	dev->send = davinci_eth_send_packet;
 	dev->recv = davinci_eth_rcv_packet;
+	dev->write_hwaddr = davinci_eth_set_mac_addr;
 
 	eth_register(dev);
 
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index 3238a50..6c161b6 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -1,4 +1,9 @@
 /*
+ * (C) Copyright 2010
+ * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de
+ * Martin Krause, Martin.Krause@tqs.de
+ * reworked original enc28j60.c
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of
@@ -6,7 +11,7 @@
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
@@ -15,968 +20,959 @@
  * MA 02111-1307 USA
  */
 
-#include <config.h>
 #include <common.h>
 #include <net.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/spi.h>
+#include <spi.h>
+#include <malloc.h>
+#include <netdev.h>
+#include <miiphy.h>
+#include "enc28j60.h"
 
 /*
- * Control Registers in Bank 0
+ * IMPORTANT: spi_claim_bus() and spi_release_bus()
+ * are called at begin and end of each of the following functions:
+ * enc_miiphy_read(), enc_miiphy_write(), enc_write_hwaddr(),
+ * enc_init(), enc_recv(), enc_send(), enc_halt()
+ * ALL other functions assume that the bus has already been claimed!
+ * Since NetReceive() might call enc_send() in return, the bus must be
+ * released, NetReceive() called and claimed again.
  */
 
-#define CTL_REG_ERDPTL	 0x00
-#define CTL_REG_ERDPTH	 0x01
-#define CTL_REG_EWRPTL	 0x02
-#define CTL_REG_EWRPTH	 0x03
-#define CTL_REG_ETXSTL	 0x04
-#define CTL_REG_ETXSTH	 0x05
-#define CTL_REG_ETXNDL	 0x06
-#define CTL_REG_ETXNDH	 0x07
-#define CTL_REG_ERXSTL	 0x08
-#define CTL_REG_ERXSTH	 0x09
-#define CTL_REG_ERXNDL	 0x0A
-#define CTL_REG_ERXNDH	 0x0B
-#define CTL_REG_ERXRDPTL 0x0C
-#define CTL_REG_ERXRDPTH 0x0D
-#define CTL_REG_ERXWRPTL 0x0E
-#define CTL_REG_ERXWRPTH 0x0F
-#define CTL_REG_EDMASTL  0x10
-#define CTL_REG_EDMASTH  0x11
-#define CTL_REG_EDMANDL  0x12
-#define CTL_REG_EDMANDH  0x13
-#define CTL_REG_EDMADSTL 0x14
-#define CTL_REG_EDMADSTH 0x15
-#define CTL_REG_EDMACSL  0x16
-#define CTL_REG_EDMACSH  0x17
-/* these are common in all banks */
-#define CTL_REG_EIE	 0x1B
-#define CTL_REG_EIR	 0x1C
-#define CTL_REG_ESTAT	 0x1D
-#define CTL_REG_ECON2	 0x1E
-#define CTL_REG_ECON1	 0x1F
-
 /*
- * Control Registers in Bank 1
+ * Controller memory layout.
+ * We only allow 1 frame for transmission and reserve the rest
+ * for reception to handle as many broadcast packets as possible.
+ * Also use the memory from 0x0000 for receiver buffer. See errata pt. 5
+ * 0x0000 - 0x19ff 6656 bytes receive buffer
+ * 0x1a00 - 0x1fff 1536 bytes transmit buffer =
+ * control(1)+frame(1518)+status(7)+reserve(10).
  */
-
-#define CTL_REG_EHT0	0x00
-#define CTL_REG_EHT1	0x01
-#define CTL_REG_EHT2	0x02
-#define CTL_REG_EHT3	0x03
-#define CTL_REG_EHT4	0x04
-#define CTL_REG_EHT5	0x05
-#define CTL_REG_EHT6	0x06
-#define CTL_REG_EHT7	0x07
-#define CTL_REG_EPMM0	0x08
-#define CTL_REG_EPMM1	0x09
-#define CTL_REG_EPMM2	0x0A
-#define CTL_REG_EPMM3	0x0B
-#define CTL_REG_EPMM4	0x0C
-#define CTL_REG_EPMM5	0x0D
-#define CTL_REG_EPMM6	0x0E
-#define CTL_REG_EPMM7	0x0F
-#define CTL_REG_EPMCSL	0x10
-#define CTL_REG_EPMCSH	0x11
-#define CTL_REG_EPMOL	0x14
-#define CTL_REG_EPMOH	0x15
-#define CTL_REG_EWOLIE	0x16
-#define CTL_REG_EWOLIR	0x17
-#define CTL_REG_ERXFCON 0x18
-#define CTL_REG_EPKTCNT 0x19
+#define ENC_RX_BUF_START	0x0000
+#define ENC_RX_BUF_END		0x19ff
+#define ENC_TX_BUF_START	0x1a00
+#define ENC_TX_BUF_END		0x1fff
+#define ENC_MAX_FRM_LEN		1518
+#define RX_RESET_COUNTER	1000
 
 /*
- * Control Registers in Bank 2
+ * For non data transfer functions, like phy read/write, set hwaddr, init
+ * we do not need a full, time consuming init including link ready wait.
+ * This enum helps to bring the chip through the minimum necessary inits.
  */
-
-#define CTL_REG_MACON1	 0x00
-#define CTL_REG_MACON2	 0x01
-#define CTL_REG_MACON3	 0x02
-#define CTL_REG_MACON4	 0x03
-#define CTL_REG_MABBIPG  0x04
-#define CTL_REG_MAIPGL	 0x06
-#define CTL_REG_MAIPGH	 0x07
-#define CTL_REG_MACLCON1 0x08
-#define CTL_REG_MACLCON2 0x09
-#define CTL_REG_MAMXFLL  0x0A
-#define CTL_REG_MAMXFLH  0x0B
-#define CTL_REG_MAPHSUP  0x0D
-#define CTL_REG_MICON	 0x11
-#define CTL_REG_MICMD	 0x12
-#define CTL_REG_MIREGADR 0x14
-#define CTL_REG_MIWRL	 0x16
-#define CTL_REG_MIWRH	 0x17
-#define CTL_REG_MIRDL	 0x18
-#define CTL_REG_MIRDH	 0x19
+enum enc_initstate {none=0, setupdone, linkready};
+typedef struct enc_device {
+	struct eth_device	*dev;	/* back pointer */
+	struct spi_slave	*slave;
+	int			rx_reset_counter;
+	u16			next_pointer;
+	u8			bank;	/* current bank in enc28j60 */
+	enum enc_initstate	initstate;
+} enc_dev_t;
 
 /*
- * Control Registers in Bank 3
- */
-
-#define CTL_REG_MAADR1	0x00
-#define CTL_REG_MAADR0	0x01
-#define CTL_REG_MAADR3	0x02
-#define CTL_REG_MAADR2	0x03
-#define CTL_REG_MAADR5	0x04
-#define CTL_REG_MAADR4	0x05
-#define CTL_REG_EBSTSD	0x06
-#define CTL_REG_EBSTCON 0x07
-#define CTL_REG_EBSTCSL 0x08
-#define CTL_REG_EBSTCSH 0x09
-#define CTL_REG_MISTAT	0x0A
-#define CTL_REG_EREVID	0x12
-#define CTL_REG_ECOCON	0x15
-#define CTL_REG_EFLOCON 0x17
-#define CTL_REG_EPAUSL	0x18
-#define CTL_REG_EPAUSH	0x19
-
-
-/*
- * PHY Register
- */
-
-#define PHY_REG_PHID1 0x02
-#define PHY_REG_PHID2 0x03
-/* taken from the Linux driver */
-#define PHY_REG_PHCON1 0x00
-#define PHY_REG_PHCON2 0x10
-#define PHY_REG_PHLCON 0x14
-
-/*
- * Receive Filter Register (ERXFCON) bits
- */
-
-#define ENC_RFR_UCEN  0x80
-#define ENC_RFR_ANDOR 0x40
-#define ENC_RFR_CRCEN 0x20
-#define ENC_RFR_PMEN  0x10
-#define ENC_RFR_MPEN  0x08
-#define ENC_RFR_HTEN  0x04
-#define ENC_RFR_MCEN  0x02
-#define ENC_RFR_BCEN  0x01
-
-/*
- * ECON1 Register Bits
- */
-
-#define ENC_ECON1_TXRST  0x80
-#define ENC_ECON1_RXRST  0x40
-#define ENC_ECON1_DMAST  0x20
-#define ENC_ECON1_CSUMEN 0x10
-#define ENC_ECON1_TXRTS  0x08
-#define ENC_ECON1_RXEN	 0x04
-#define ENC_ECON1_BSEL1  0x02
-#define ENC_ECON1_BSEL0  0x01
-
-/*
- * ECON2 Register Bits
- */
-#define ENC_ECON2_AUTOINC 0x80
-#define ENC_ECON2_PKTDEC  0x40
-#define ENC_ECON2_PWRSV   0x20
-#define ENC_ECON2_VRPS	  0x08
-
-/*
- * EIR Register Bits
- */
-#define ENC_EIR_PKTIF  0x40
-#define ENC_EIR_DMAIF  0x20
-#define ENC_EIR_LINKIF 0x10
-#define ENC_EIR_TXIF   0x08
-#define ENC_EIR_WOLIF  0x04
-#define ENC_EIR_TXERIF 0x02
-#define ENC_EIR_RXERIF 0x01
-
-/*
- * ESTAT Register Bits
- */
-
-#define ENC_ESTAT_INT	  0x80
-#define ENC_ESTAT_LATECOL 0x10
-#define ENC_ESTAT_RXBUSY  0x04
-#define ENC_ESTAT_TXABRT  0x02
-#define ENC_ESTAT_CLKRDY  0x01
-
-/*
- * EIE Register Bits
- */
-
-#define ENC_EIE_INTIE  0x80
-#define ENC_EIE_PKTIE  0x40
-#define ENC_EIE_DMAIE  0x20
-#define ENC_EIE_LINKIE 0x10
-#define ENC_EIE_TXIE   0x08
-#define ENC_EIE_WOLIE  0x04
-#define ENC_EIE_TXERIE 0x02
-#define ENC_EIE_RXERIE 0x01
-
-/*
- * MACON1 Register Bits
- */
-#define ENC_MACON1_LOOPBK  0x10
-#define ENC_MACON1_TXPAUS  0x08
-#define ENC_MACON1_RXPAUS  0x04
-#define ENC_MACON1_PASSALL 0x02
-#define ENC_MACON1_MARXEN  0x01
-
-
-/*
- * MACON2 Register Bits
- */
-#define ENC_MACON2_MARST   0x80
-#define ENC_MACON2_RNDRST  0x40
-#define ENC_MACON2_MARXRST 0x08
-#define ENC_MACON2_RFUNRST 0x04
-#define ENC_MACON2_MATXRST 0x02
-#define ENC_MACON2_TFUNRST 0x01
-
-/*
- * MACON3 Register Bits
- */
-#define ENC_MACON3_PADCFG2 0x80
-#define ENC_MACON3_PADCFG1 0x40
-#define ENC_MACON3_PADCFG0 0x20
-#define ENC_MACON3_TXCRCEN 0x10
-#define ENC_MACON3_PHDRLEN 0x08
-#define ENC_MACON3_HFRMEN  0x04
-#define ENC_MACON3_FRMLNEN 0x02
-#define ENC_MACON3_FULDPX  0x01
-
-/*
- * MICMD Register Bits
- */
-#define ENC_MICMD_MIISCAN 0x02
-#define ENC_MICMD_MIIRD   0x01
-
-/*
- * MISTAT Register Bits
- */
-#define ENC_MISTAT_NVALID 0x04
-#define ENC_MISTAT_SCAN   0x02
-#define ENC_MISTAT_BUSY   0x01
-
-/*
- * PHID1 and PHID2 values
- */
-#define ENC_PHID1_VALUE 0x0083
-#define ENC_PHID2_VALUE 0x1400
-#define ENC_PHID2_MASK	0xFC00
-
-
-#define ENC_SPI_SLAVE_CS 0x00010000	/* pin P1.16 */
-#define ENC_RESET	 0x00020000	/* pin P1.17 */
-
-#define FAILSAFE_VALUE 5000
-
-/*
- * Controller memory layout:
+ * enc_bset:		set bits in a common register
+ * enc_bclr:		clear bits in a common register
  *
- * 0x0000 - 0x17ff  6k bytes receive buffer
- * 0x1800 - 0x1fff  2k bytes transmit buffer
+ * making the reg parameter u8 will give a compile time warning if the
+ * functions are called with a register not accessible in all Banks
  */
-/* Use the lower memory for receiver buffer. See errata pt. 5 */
-#define ENC_RX_BUF_START 0x0000
-#define ENC_TX_BUF_START 0x1800
-/* taken from the Linux driver */
-#define ENC_RX_BUF_END   0x17ff
-#define ENC_TX_BUF_END   0x1fff
-
-/* maximum frame length */
-#define ENC_MAX_FRM_LEN 1518
-
-#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS)
-#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS)
-#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8);
-
-
-static unsigned char encReadReg (unsigned char regNo);
-static void encWriteReg (unsigned char regNo, unsigned char data);
-static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c);
-static void encReadBuff (unsigned short length, unsigned char *pBuff);
-static void encWriteBuff (unsigned short length, unsigned char *pBuff);
-static void encBitSet (unsigned char regNo, unsigned char data);
-static void encBitClr (unsigned char regNo, unsigned char data);
-static void encReset (void);
-static void encInit (unsigned char *pEthAddr);
-static unsigned short phyRead (unsigned char addr);
-static void phyWrite(unsigned char, unsigned short);
-static void encPoll (void);
-static void encRx (void);
-
-#define m_nic_read(reg) encReadReg(reg)
-#define m_nic_write(reg, data) encWriteReg(reg, data)
-#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count)
-#define m_nic_read_data(len, buf) encReadBuff((len), (buf))
-#define m_nic_write_data(len, buf) encWriteBuff((len), (buf))
-
-/* bit field set */
-#define m_nic_bfs(reg, data) encBitSet(reg, data)
-
-/* bit field clear */
-#define m_nic_bfc(reg, data) encBitClr(reg, data)
-
-static unsigned char bank = 0;	/* current bank in enc28j60 */
-static unsigned char next_pointer_lsb;
-static unsigned char next_pointer_msb;
-
-static unsigned char buffer[ENC_MAX_FRM_LEN];
-static int rxResetCounter = 0;
-
-#define RX_RESET_COUNTER 1000;
-
-/*-----------------------------------------------------------------------------
- * Always returns 0
- */
-int eth_init (bd_t * bis)
+static void enc_bset(enc_dev_t *enc, const u8 reg, const u8 data)
 {
-	unsigned char estatVal;
-	uchar enetaddr[6];
+	u8 dout[2];
 
-	/* configure GPIO */
-	(*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS;
-	(*((volatile unsigned long *) IO1DIR)) |= ENC_RESET;
+	dout[0] = CMD_BFS(reg);
+	dout[1] = data;
+	spi_xfer(enc->slave, 2 * 8, dout, NULL,
+		SPI_XFER_BEGIN | SPI_XFER_END);
+}
 
-	/* CS and RESET active low */
-	PUT32 (IO1SET, ENC_SPI_SLAVE_CS);
-	PUT32 (IO1SET, ENC_RESET);
+static void enc_bclr(enc_dev_t *enc, const u8 reg, const u8 data)
+{
+	u8 dout[2];
 
-	spi_init ();
+	dout[0] = CMD_BFC(reg);
+	dout[1] = data;
+	spi_xfer(enc->slave, 2 * 8, dout, NULL,
+		SPI_XFER_BEGIN | SPI_XFER_END);
+}
 
-	/* taken from the Linux driver - dangerous stuff here! */
-	/* Wait for CLKRDY to become set (i.e., check that we can communicate with
-	   the ENC) */
+/*
+ * high byte of the register contains bank number:
+ * 0: no bank switch necessary
+ * 1: switch to bank 0
+ * 2: switch to bank 1
+ * 3: switch to bank 2
+ * 4: switch to bank 3
+ */
+static void enc_set_bank(enc_dev_t *enc, const u16 reg)
+{
+	u8 newbank = reg >> 8;
+
+	if (newbank == 0 || newbank == enc->bank)
+		return;
+	switch (newbank) {
+	case 1:
+		enc_bclr(enc, CTL_REG_ECON1,
+			ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1);
+		break;
+	case 2:
+		enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_BSEL0);
+		enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_BSEL1);
+		break;
+	case 3:
+		enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_BSEL0);
+		enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_BSEL1);
+		break;
+	case 4:
+		enc_bset(enc, CTL_REG_ECON1,
+			ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1);
+		break;
+	}
+	enc->bank = newbank;
+}
+
+/*
+ * local functions to access SPI
+ *
+ * reg: register inside ENC28J60
+ * data: 8/16 bits to write
+ * c: number of retries
+ *
+ * enc_r8:		read 8 bits
+ * enc_r16:		read 16 bits
+ * enc_w8:		write 8 bits
+ * enc_w16:		write 16 bits
+ * enc_w8_retry:	write 8 bits, verify and retry
+ * enc_rbuf:		read from ENC28J60 into buffer
+ * enc_wbuf:		write from buffer into ENC28J60
+ */
+
+/*
+ * MAC and MII registers need a 3 byte SPI transfer to read,
+ * all other registers need a 2 byte SPI transfer.
+ */
+static int enc_reg2nbytes(const u16 reg)
+{
+	/* check if MAC or MII register */
+	return ((reg >= CTL_REG_MACON1 && reg <= CTL_REG_MIRDH) ||
+		(reg >= CTL_REG_MAADR1 && reg <= CTL_REG_MAADR4) ||
+		(reg == CTL_REG_MISTAT)) ? 3 : 2;
+}
+
+/*
+ * Read a byte register
+ */
+static u8 enc_r8(enc_dev_t *enc, const u16 reg)
+{
+	u8 dout[3];
+	u8 din[3];
+	int nbytes = enc_reg2nbytes(reg);
+
+	enc_set_bank(enc, reg);
+	dout[0] = CMD_RCR(reg);
+	spi_xfer(enc->slave, nbytes * 8, dout, din,
+		SPI_XFER_BEGIN | SPI_XFER_END);
+	return din[nbytes-1];
+}
+
+/*
+ * Read a L/H register pair and return a word.
+ * Must be called with the L register's address.
+ */
+static u16 enc_r16(enc_dev_t *enc, const u16 reg)
+{
+	u8 dout[3];
+	u8 din[3];
+	u16 result;
+	int nbytes = enc_reg2nbytes(reg);
+
+	enc_set_bank(enc, reg);
+	dout[0] = CMD_RCR(reg);
+	spi_xfer(enc->slave, nbytes * 8, dout, din,
+		SPI_XFER_BEGIN | SPI_XFER_END);
+	result = din[nbytes-1];
+	dout[0]++; /* next register */
+	spi_xfer(enc->slave, nbytes * 8, dout, din,
+		SPI_XFER_BEGIN | SPI_XFER_END);
+	result |= din[nbytes-1] << 8;
+	return result;
+}
+
+/*
+ * Write a byte register
+ */
+static void enc_w8(enc_dev_t *enc, const u16 reg, const u8 data)
+{
+	u8 dout[2];
+
+	enc_set_bank(enc, reg);
+	dout[0] = CMD_WCR(reg);
+	dout[1] = data;
+	spi_xfer(enc->slave, 2 * 8, dout, NULL,
+		SPI_XFER_BEGIN | SPI_XFER_END);
+}
+
+/*
+ * Write a L/H register pair.
+ * Must be called with the L register's address.
+ */
+static void enc_w16(enc_dev_t *enc, const u16 reg, const u16 data)
+{
+	u8 dout[2];
+
+	enc_set_bank(enc, reg);
+	dout[0] = CMD_WCR(reg);
+	dout[1] = data;
+	spi_xfer(enc->slave, 2 * 8, dout, NULL,
+		SPI_XFER_BEGIN | SPI_XFER_END);
+	dout[0]++; /* next register */
+	dout[1] = data >> 8;
+	spi_xfer(enc->slave, 2 * 8, dout, NULL,
+		SPI_XFER_BEGIN | SPI_XFER_END);
+}
+
+/*
+ * Write a byte register, verify and retry
+ */
+static void enc_w8_retry(enc_dev_t *enc, const u16 reg, const u8 data, const int c)
+{
+	u8 dout[2];
+	u8 readback;
+	int i;
+
+	enc_set_bank(enc, reg);
+	for (i = 0; i < c; i++) {
+		dout[0] = CMD_WCR(reg);
+		dout[1] = data;
+		spi_xfer(enc->slave, 2 * 8, dout, NULL,
+			SPI_XFER_BEGIN | SPI_XFER_END);
+		readback = enc_r8(enc, reg);
+		if (readback == data)
+			break;
+		/* wait 1ms */
+		udelay(1000);
+	}
+	if (i == c) {
+		printf("%s: write reg 0x%03x failed\n", enc->dev->name, reg);
+	}
+}
+
+/*
+ * Read ENC RAM into buffer
+ */
+static void enc_rbuf(enc_dev_t *enc, const u16 length, u8 *buf)
+{
+	u8 dout[1];
+
+	dout[0] = CMD_RBM;
+	spi_xfer(enc->slave, 8, dout, NULL, SPI_XFER_BEGIN);
+	spi_xfer(enc->slave, length * 8, NULL, buf, SPI_XFER_END);
+#ifdef DEBUG
+	puts("Rx:\n");
+	print_buffer(0, buf, 1, length, 0);
+#endif
+}
+
+/*
+ * Write buffer into ENC RAM
+ */
+static void enc_wbuf(enc_dev_t *enc, const u16 length, const u8 *buf, const u8 control)
+{
+	u8 dout[2];
+	dout[0] = CMD_WBM;
+	dout[1] = control;
+	spi_xfer(enc->slave, 2 * 8, dout, NULL, SPI_XFER_BEGIN);
+	spi_xfer(enc->slave, length * 8, buf, NULL, SPI_XFER_END);
+#ifdef DEBUG
+	puts("Tx:\n");
+	print_buffer(0, buf, 1, length, 0);
+#endif
+}
+
+/*
+ * Try to claim the SPI bus.
+ * Print error message on failure.
+ */
+static int enc_claim_bus(enc_dev_t *enc)
+{
+	int rc = spi_claim_bus(enc->slave);
+	if (rc)
+		printf("%s: failed to claim SPI bus\n", enc->dev->name);
+	return rc;
+}
+
+/*
+ * Release previously claimed SPI bus.
+ * This function is mainly for symmetry to enc_claim_bus().
+ * Let the toolchain decide to inline it...
+ */
+static void enc_release_bus(enc_dev_t *enc)
+{
+	spi_release_bus(enc->slave);
+}
+
+/*
+ * Read PHY register
+ */
+static u16 phy_read(enc_dev_t *enc, const u8 addr)
+{
+	uint64_t etime;
+	u8 status;
+
+	enc_w8(enc, CTL_REG_MIREGADR, addr);
+	enc_w8(enc, CTL_REG_MICMD, ENC_MICMD_MIIRD);
+	/* 1 second timeout - only happens on hardware problem */
+	etime = get_ticks() + get_tbclk();
+	/* poll MISTAT.BUSY bit until operation is complete */
 	do
 	{
-		estatVal = m_nic_read(CTL_REG_ESTAT);
-	} while ((estatVal & 0x08) || (~estatVal & ENC_ESTAT_CLKRDY));
-
-	/* initialize controller */
-	encReset ();
-	eth_getenv_enetaddr("ethaddr", enetaddr);
-	encInit (enetaddr);
-
-	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN);	/* enable receive */
-
-	return 0;
-}
-
-int eth_send (volatile void *packet, int length)
-{
-	/* check frame length, etc. */
-	/* TODO: */
-
-	/* switch to bank 0 */
-	m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
-
-	/* set EWRPT */
-	m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff));
-	m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8));
-
-	/* set ETXND */
-	m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF);
-	m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8);
-
-	/* set ETXST */
-	m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF);
-	m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8);
-
-	/* write packet */
-	m_nic_write_data (length, (unsigned char *) packet);
-
-	/* taken from the Linux driver */
-	/* Verify that the internal transmit logic has not been altered by excessive
-	   collisions.  See Errata B4 12 and 14.
-	 */
-	if (m_nic_read(CTL_REG_EIR) & ENC_EIR_TXERIF) {
-		m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRST);
-		m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_TXRST);
+		status = enc_r8(enc, CTL_REG_MISTAT);
+	} while (get_ticks() <= etime && (status & ENC_MISTAT_BUSY));
+	if (status & ENC_MISTAT_BUSY) {
+		printf("%s: timeout reading phy\n", enc->dev->name);
+		return 0;
 	}
-	m_nic_bfc(CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF));
-
-	/* set ECON1.TXRTS */
-	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS);
-
-	return 0;
+	enc_w8(enc, CTL_REG_MICMD, 0);
+	return enc_r16(enc, CTL_REG_MIRDL);
 }
 
-
-/*****************************************************************************
- * This function resets the receiver only. This function may be called from
- * interrupt-context.
+/*
+ * Write PHY register
  */
-static void encReceiverReset (void)
+static void phy_write(enc_dev_t *enc, const u8 addr, const u16 data)
 {
-	unsigned char econ1;
+	uint64_t etime;
+	u8 status;
 
-	econ1 = m_nic_read (CTL_REG_ECON1);
-	if ((econ1 & ENC_ECON1_RXRST) == 0) {
-		m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST);
-		rxResetCounter = RX_RESET_COUNTER;
+	enc_w8(enc, CTL_REG_MIREGADR, addr);
+	enc_w16(enc, CTL_REG_MIWRL, data);
+	/* 1 second timeout - only happens on hardware problem */
+	etime = get_ticks() + get_tbclk();
+	/* poll MISTAT.BUSY bit until operation is complete */
+	do
+	{
+		status = enc_r8(enc, CTL_REG_MISTAT);
+	} while (get_ticks() <= etime && (status & ENC_MISTAT_BUSY));
+	if (status & ENC_MISTAT_BUSY) {
+		printf("%s: timeout writing phy\n", enc->dev->name);
+		return;
 	}
 }
 
-/*****************************************************************************
- * receiver reset timer
+/*
+ * Verify link status, wait if necessary
+ *
+ * Note: with a 10 MBit/s only PHY there is no autonegotiation possible,
+ * half/full duplex is a pure setup matter. For the time being, this driver
+ * will setup in half duplex mode only.
  */
-static void encReceiverResetCallback (void)
+static int enc_phy_link_wait(enc_dev_t *enc)
 {
-	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST);
-	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN);	/* enable receive */
-}
+	u16 status;
+	int duplex;
+	uint64_t etime;
 
-/*-----------------------------------------------------------------------------
- * Check for received packets. Call NetReceive for each packet. The return
- * value is ignored by the caller.
- */
-int eth_rx (void)
-{
-	if (rxResetCounter > 0 && --rxResetCounter == 0) {
-		encReceiverResetCallback ();
-	}
-
-	encPoll ();
-
-	return 0;
-}
-
-void eth_halt (void)
-{
-	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN);	/* disable receive */
-}
-
-/*****************************************************************************/
-
-static void encPoll (void)
-{
-	unsigned char eir_reg;
-	volatile unsigned char estat_reg;
-	unsigned char pkt_cnt;
-
-#ifdef CONFIG_USE_IRQ
-	/* clear global interrupt enable bit in enc28j60 */
-	m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE);
+#ifdef CONFIG_ENC_SILENTLINK
+	/* check if we have a link, then just return */
+	status = phy_read(enc, PHY_REG_PHSTAT1);
+	if (status & ENC_PHSTAT1_LLSTAT)
+		return 0;
 #endif
-	estat_reg = m_nic_read (CTL_REG_ESTAT);
 
-	eir_reg = m_nic_read (CTL_REG_EIR);
-
-	if (eir_reg & ENC_EIR_TXIF) {
-		/* clear TXIF bit in EIR */
-		m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF);
-	}
-
-	/* We have to use pktcnt and not pktif bit, see errata pt. 6 */
-
-	/* move to bank 1 */
-	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
-	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
-
-	/* read pktcnt */
-	pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
-
-	if (pkt_cnt > 0) {
-		if ((eir_reg & ENC_EIR_PKTIF) == 0) {
-			/*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */
+	/* wait for link with 1 second timeout */
+	etime = get_ticks() + get_tbclk();
+	while (get_ticks() <= etime) {
+		status = phy_read(enc, PHY_REG_PHSTAT1);
+		if (status & ENC_PHSTAT1_LLSTAT) {
+			/* now we have a link */
+			status = phy_read(enc, PHY_REG_PHSTAT2);
+			duplex = (status & ENC_PHSTAT2_DPXSTAT) ? 1 : 0;
+			printf("%s: link up, 10Mbps %s-duplex\n",
+				enc->dev->name, duplex ? "full" : "half");
+			return 0;
 		}
-		encRx ();
-		/* clear PKTIF bit in EIR, this should not need to be done but it
-		   seems like we get problems if we do not */
-		m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF);
+		udelay(1000);
 	}
 
-	if (eir_reg & ENC_EIR_RXERIF) {
-		printf ("encPoll: rx error\n");
-		m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF);
-	}
-	if (eir_reg & ENC_EIR_TXERIF) {
-		printf ("encPoll: tx error\n");
-		m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF);
-	}
-
-#ifdef CONFIG_USE_IRQ
-	/* set global interrupt enable bit in enc28j60 */
-	m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
-#endif
+	/* timeout occured */
+	printf("%s: link down\n", enc->dev->name);
+	return 1;
 }
 
-static void encRx (void)
+/*
+ * This function resets the receiver only.
+ */
+static void enc_reset_rx(enc_dev_t *enc)
 {
-	unsigned short pkt_len;
-	unsigned short copy_len;
-	unsigned short status;
-	unsigned char eir_reg;
-	unsigned char pkt_cnt = 0;
-	unsigned short rxbuf_rdpt;
+	u8 econ1;
 
-	/* switch to bank 0 */
-	m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+	econ1 = enc_r8(enc, CTL_REG_ECON1);
+	if ((econ1 & ENC_ECON1_RXRST) == 0) {
+		enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXRST);
+		enc->rx_reset_counter = RX_RESET_COUNTER;
+	}
+}
 
-	m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
-	m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
+/*
+ * Reset receiver and reenable it.
+ */
+static void enc_reset_rx_call(enc_dev_t *enc)
+{
+	enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_RXRST);
+	enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
+}
 
+/*
+ * Copy a packet from the receive ring and forward it to
+ * the protocol stack.
+ */
+static void enc_receive(enc_dev_t *enc)
+{
+	u8 *packet = (u8 *)NetRxPackets[0];
+	u16 pkt_len;
+	u16 copy_len;
+	u16 status;
+	u8 eir_reg;
+	u8 pkt_cnt = 0;
+	u16 rxbuf_rdpt;
+	u8 hbuf[6];
+
+	enc_w16(enc, CTL_REG_ERDPTL, enc->next_pointer);
 	do {
-		m_nic_read_data (6, buffer);
-		next_pointer_lsb = buffer[0];
-		next_pointer_msb = buffer[1];
-		pkt_len = buffer[2];
-		pkt_len |= (unsigned short) buffer[3] << 8;
-		status = buffer[4];
-		status |= (unsigned short) buffer[5] << 8;
-
+		enc_rbuf(enc, 6, hbuf);
+		enc->next_pointer = hbuf[0] | (hbuf[1] << 8);
+		pkt_len = hbuf[2] | (hbuf[3] << 8);
+		status = hbuf[4] | (hbuf[5] << 8);
+		debug("next_pointer=$%04x pkt_len=%u status=$%04x\n",
+			enc->next_pointer, pkt_len, status);
 		if (pkt_len <= ENC_MAX_FRM_LEN)
 			copy_len = pkt_len;
 		else
 			copy_len = 0;
-
 		if ((status & (1L << 7)) == 0) /* check Received Ok bit */
 			copy_len = 0;
-
-		/* taken from the Linux driver */
 		/* check if next pointer is resonable */
-		if ((((unsigned int)next_pointer_msb << 8) |
-			(unsigned int)next_pointer_lsb) >= ENC_TX_BUF_START)
+		if (enc->next_pointer >= ENC_TX_BUF_START)
 			copy_len = 0;
-
 		if (copy_len > 0) {
-			m_nic_read_data (copy_len, buffer);
+			enc_rbuf(enc, copy_len, packet);
 		}
-
 		/* advance read pointer to next pointer */
-		m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
-		m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
-
+		enc_w16(enc, CTL_REG_ERDPTL, enc->next_pointer);
 		/* decrease packet counter */
-		m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC);
-
-		/* taken from the Linux driver */
-		/* Only odd values should be written to ERXRDPTL,
+		enc_bset(enc, CTL_REG_ECON2, ENC_ECON2_PKTDEC);
+		/*
+		 * Only odd values should be written to ERXRDPTL,
 		 * see errata B4 pt.13
 		 */
-		rxbuf_rdpt = (next_pointer_msb << 8 | next_pointer_lsb) - 1;
-		if ((rxbuf_rdpt < (m_nic_read(CTL_REG_ERXSTH) << 8 |
-				m_nic_read(CTL_REG_ERXSTL))) || (rxbuf_rdpt >
-				(m_nic_read(CTL_REG_ERXNDH) << 8 |
-				m_nic_read(CTL_REG_ERXNDL)))) {
-			m_nic_write(CTL_REG_ERXRDPTL, m_nic_read(CTL_REG_ERXNDL));
-			m_nic_write(CTL_REG_ERXRDPTH, m_nic_read(CTL_REG_ERXNDH));
+		rxbuf_rdpt = enc->next_pointer - 1;
+		if ((rxbuf_rdpt < enc_r16(enc, CTL_REG_ERXSTL)) ||
+			(rxbuf_rdpt > enc_r16(enc, CTL_REG_ERXNDL))) {
+			enc_w16(enc, CTL_REG_ERXRDPTL,
+				enc_r16(enc, CTL_REG_ERXNDL));
 		} else {
-			m_nic_write(CTL_REG_ERXRDPTL, rxbuf_rdpt & 0xFF);
-			m_nic_write(CTL_REG_ERXRDPTH, rxbuf_rdpt >> 8);
+			enc_w16(enc, CTL_REG_ERXRDPTL, rxbuf_rdpt);
 		}
-
-		/* move to bank 1 */
-		m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
-		m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
-
 		/* read pktcnt */
-		pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
-
-		/* switch to bank 0 */
-		m_nic_bfc (CTL_REG_ECON1,
-			   (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
-
+		pkt_cnt = enc_r8(enc, CTL_REG_EPKTCNT);
 		if (copy_len == 0) {
-			eir_reg = m_nic_read (CTL_REG_EIR);
-			encReceiverReset ();
-			printf ("eth_rx: copy_len=0\n");
+			eir_reg = enc_r8(enc, CTL_REG_EIR);
+			enc_reset_rx(enc);
+			printf("%s: receive copy_len=0\n", enc->dev->name);
 			continue;
 		}
-
-		NetReceive ((unsigned char *) buffer, pkt_len);
-
-		eir_reg = m_nic_read (CTL_REG_EIR);
-	} while (pkt_cnt);	/* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
+		/*
+		 * Because NetReceive() might call enc_send(), we need to
+		 * release the SPI bus, call NetReceive(), reclaim the bus
+		 */
+		enc_release_bus(enc);
+		NetReceive(packet, pkt_len);
+		if (enc_claim_bus(enc))
+			return;
+		eir_reg = enc_r8(enc, CTL_REG_EIR);
+	} while (pkt_cnt);
+	/* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
 }
 
-static void encWriteReg (unsigned char regNo, unsigned char data)
+/*
+ * Poll for completely received packets.
+ */
+static void enc_poll(enc_dev_t *enc)
 {
-	spi_lock ();
-	enc_cfg_spi ();
-	enc_enable ();
+	u8 eir_reg;
+	u8 estat_reg;
+	u8 pkt_cnt;
 
-	spi_write (0x40 | regNo);	/* write in regNo */
-	spi_write (data);
-
-	enc_disable ();
-	enc_enable ();
-
-	spi_write (0x1f);	/* write reg 0x1f */
-
-	enc_disable ();
-	spi_unlock ();
-}
-
-static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c)
-{
-	unsigned char readback;
-	int i;
-
-	spi_lock ();
-
-	for (i = 0; i < c; i++) {
-		enc_cfg_spi ();
-		enc_enable ();
-
-		spi_write (0x40 | regNo);	/* write in regNo */
-		spi_write (data);
-
-		enc_disable ();
-		enc_enable ();
-
-		spi_write (0x1f);	/* write reg 0x1f */
-
-		enc_disable ();
-
-		spi_unlock ();	/* we must unlock spi first */
-
-		readback = encReadReg (regNo);
-
-		spi_lock ();
-
-		if (readback == data)
-			break;
+#ifdef CONFIG_USE_IRQ
+	/* clear global interrupt enable bit in enc28j60 */
+	enc_bclr(enc, CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+	estat_reg = enc_r8(enc, CTL_REG_ESTAT);
+	eir_reg = enc_r8(enc, CTL_REG_EIR);
+	if (eir_reg & ENC_EIR_TXIF) {
+		/* clear TXIF bit in EIR */
+		enc_bclr(enc, CTL_REG_EIR, ENC_EIR_TXIF);
 	}
-	spi_unlock ();
-
-	if (i == c) {
-		printf ("enc28j60: write reg %d failed\n", regNo);
+	/* We have to use pktcnt and not pktif bit, see errata pt. 6 */
+	pkt_cnt = enc_r8(enc, CTL_REG_EPKTCNT);
+	if (pkt_cnt > 0) {
+		if ((eir_reg & ENC_EIR_PKTIF) == 0) {
+			debug("enc_poll: pkt cnt > 0, but pktif not set\n");
+		}
+		enc_receive(enc);
+		/*
+		 * clear PKTIF bit in EIR, this should not need to be done
+		 * but it seems like we get problems if we do not
+		 */
+		enc_bclr(enc, CTL_REG_EIR, ENC_EIR_PKTIF);
 	}
-}
-
-static unsigned char encReadReg (unsigned char regNo)
-{
-	unsigned char rxByte;
-
-	spi_lock ();
-	enc_cfg_spi ();
-	enc_enable ();
-
-	spi_write (0x1f);	/* read reg 0x1f */
-
-	bank = spi_read () & 0x3;
-
-	enc_disable ();
-	enc_enable ();
-
-	spi_write (regNo);
-	rxByte = spi_read ();
-
-	/* check if MAC or MII register */
-	if (((bank == 2) && (regNo <= 0x1a)) ||
-	    ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) {
-		/* ignore first byte and read another byte */
-		rxByte = spi_read ();
+	if (eir_reg & ENC_EIR_RXERIF) {
+		printf("%s: rx error\n", enc->dev->name);
+		enc_bclr(enc, CTL_REG_EIR, ENC_EIR_RXERIF);
 	}
-
-	enc_disable ();
-	spi_unlock ();
-
-	return rxByte;
-}
-
-static void encReadBuff (unsigned short length, unsigned char *pBuff)
-{
-	spi_lock ();
-	enc_cfg_spi ();
-	enc_enable ();
-
-	spi_write (0x20 | 0x1a);	/* read buffer memory */
-
-	while (length--) {
-		if (pBuff != NULL)
-			*pBuff++ = spi_read ();
-		else
-			spi_write (0);
+	if (eir_reg & ENC_EIR_TXERIF) {
+		printf("%s: tx error\n", enc->dev->name);
+		enc_bclr(enc, CTL_REG_EIR, ENC_EIR_TXERIF);
 	}
-
-	enc_disable ();
-	spi_unlock ();
+#ifdef CONFIG_USE_IRQ
+	/* set global interrupt enable bit in enc28j60 */
+	enc_bset(enc, CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
 }
 
-static void encWriteBuff (unsigned short length, unsigned char *pBuff)
+/*
+ * Completely Reset the ENC
+ */
+static void enc_reset(enc_dev_t *enc)
 {
-	spi_lock ();
-	enc_cfg_spi ();
-	enc_enable ();
+	u8 dout[1];
 
-	spi_write (0x60 | 0x1a);	/* write buffer memory */
-
-	spi_write (0x00);	/* control byte */
-
-	while (length--)
-		spi_write (*pBuff++);
-
-	enc_disable ();
-	spi_unlock ();
-}
-
-static void encBitSet (unsigned char regNo, unsigned char data)
-{
-	spi_lock ();
-	enc_cfg_spi ();
-	enc_enable ();
-
-	spi_write (0x80 | regNo);	/* bit field set */
-	spi_write (data);
-
-	enc_disable ();
-	spi_unlock ();
-}
-
-static void encBitClr (unsigned char regNo, unsigned char data)
-{
-	spi_lock ();
-	enc_cfg_spi ();
-	enc_enable ();
-
-	spi_write (0xA0 | regNo);	/* bit field clear */
-	spi_write (data);
-
-	enc_disable ();
-	spi_unlock ();
-}
-
-static void encReset (void)
-{
-	spi_lock ();
-	enc_cfg_spi ();
-	enc_enable ();
-
-	spi_write (0xff);	/* soft reset */
-
-	enc_disable ();
-	spi_unlock ();
-
+	dout[0] = CMD_SRC;
+	spi_xfer(enc->slave, 8, dout, NULL,
+		SPI_XFER_BEGIN | SPI_XFER_END);
 	/* sleep 1 ms. See errata pt. 2 */
-	udelay (1000);
+	udelay(1000);
 }
 
-static void encInit (unsigned char *pEthAddr)
-{
-	unsigned short phid1 = 0;
-	unsigned short phid2 = 0;
-
-	/* switch to bank 0 */
-	m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
-
+/*
+ * Initialisation data for most of the ENC registers
+ */
+static const u16 enc_initdata[] = {
 	/*
 	 * Setup the buffer space. The reset values are valid for the
 	 * other pointers.
+	 *
+	 * We shall not write to ERXST, see errata pt. 5. Instead we
+	 * have to make sure that ENC_RX_BUS_START is 0.
 	 */
-	/* We shall not write to ERXST, see errata pt. 5. Instead we
-	   have to make sure that ENC_RX_BUS_START is 0. */
-	m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1);
-	m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1);
-
-	/* taken from the Linux driver */
-	m_nic_write_retry (CTL_REG_ERXNDL, (ENC_RX_BUF_END & 0xFF), 1);
-	m_nic_write_retry (CTL_REG_ERXNDH, (ENC_RX_BUF_END >> 8), 1);
-
-	m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1);
-	m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1);
-
-	next_pointer_lsb = (ENC_RX_BUF_START & 0xFF);
-	next_pointer_msb = (ENC_RX_BUF_START >> 8);
-
-	/* verify identification */
-	phid1 = phyRead (PHY_REG_PHID1);
-	phid2 = phyRead (PHY_REG_PHID2);
-
-	if (phid1 != ENC_PHID1_VALUE
-	    || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) {
-		printf ("ERROR: failed to identify controller\n");
-		printf ("phid1 = %x, phid2 = %x\n",
-			phid1, (phid2 & ENC_PHID2_MASK));
-		printf ("should be phid1 = %x, phid2 = %x\n",
-			ENC_PHID1_VALUE, ENC_PHID2_VALUE);
-	}
-
+	CTL_REG_ERXSTL, ENC_RX_BUF_START,
+	CTL_REG_ERXSTH, ENC_RX_BUF_START >> 8,
+	CTL_REG_ERXNDL, ENC_RX_BUF_END,
+	CTL_REG_ERXNDH, ENC_RX_BUF_END >> 8,
+	CTL_REG_ERDPTL, ENC_RX_BUF_START,
+	CTL_REG_ERDPTH, ENC_RX_BUF_START >> 8,
 	/*
-	 * --- MAC Initialization ---
+	 * Set the filter to receive only good-CRC, unicast and broadcast
+	 * frames.
+	 * Note: some DHCP servers return their answers as broadcasts!
+	 * So its unwise to remove broadcast from this. This driver
+	 * might incur receiver overruns with packet loss on a broadcast
+	 * flooded network.
 	 */
-
-	/* Pull MAC out of Reset */
-
-	/* switch to bank 2 */
-	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
-	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+	CTL_REG_ERXFCON, ENC_RFR_BCEN | ENC_RFR_UCEN | ENC_RFR_CRCEN,
 
 	/* enable MAC to receive frames */
-	/* added some bits from the Linux driver */
-	m_nic_write_retry (CTL_REG_MACON1
-		,(ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS)
-		,10);
+	CTL_REG_MACON1,
+		ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS,
 
 	/* configure pad, tx-crc and duplex */
-	/* added a bit from the Linux driver */
-	m_nic_write_retry (CTL_REG_MACON3
-		,(ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN | ENC_MACON3_FRMLNEN)
-		,10);
+	CTL_REG_MACON3,
+		ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN |
+		ENC_MACON3_FRMLNEN,
 
-	/* added 4 new lines from the Linux driver */
 	/* Allow infinite deferals if the medium is continously busy */
-	m_nic_write_retry(CTL_REG_MACON4, (1<<6) /*ENC_MACON4_DEFER*/, 10);
+	CTL_REG_MACON4, ENC_MACON4_DEFER,
 
 	/* Late collisions occur beyond 63 bytes */
-	m_nic_write_retry(CTL_REG_MACLCON2, 63, 10);
-
-	/* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */
-	m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10);
+	CTL_REG_MACLCON2, 63,
 
 	/*
-	* Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended
-	* 0x0c for half-duplex. Nothing for full-duplex
-	*/
-	m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10);
+	 * Set (low byte) Non-Back-to_Back Inter-Packet Gap.
+	 * Recommended 0x12
+	 */
+	CTL_REG_MAIPGL, 0x12,
+
+	/*
+	 * Set (high byte) Non-Back-to_Back Inter-Packet Gap.
+	 * Recommended 0x0c for half-duplex. Nothing for full-duplex
+	 */
+	CTL_REG_MAIPGH, 0x0C,
 
 	/* set maximum frame length */
-	m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10);
-	m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10);
+	CTL_REG_MAMXFLL, ENC_MAX_FRM_LEN,
+	CTL_REG_MAMXFLH, ENC_MAX_FRM_LEN >> 8,
 
 	/*
-	 * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex
+	 * Set MAC back-to-back inter-packet gap.
+	 * Recommended 0x12 for half duplex
 	 * and 0x15 for full duplex.
 	 */
-	m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10);
+	CTL_REG_MABBIPG, 0x12,
 
-	/* set MAC address */
+	/* end of table */
+	0xffff
+};
 
-	/* switch to bank 3 */
-	m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1));
+/*
+ * Wait for the XTAL oscillator to become ready
+ */
+static int enc_clock_wait(enc_dev_t *enc)
+{
+	uint64_t etime;
 
-	m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1);
-	m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1);
-	m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1);
-	m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1);
-	m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1);
-	m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1);
+	/* one second timeout */
+	etime = get_ticks() + get_tbclk();
 
 	/*
-	* PHY Initialization taken from the Linux driver
+	 * Wait for CLKRDY to become set (i.e., check that we can
+	 * communicate with the ENC)
 	 */
+	do
+	{
+		if (enc_r8(enc, CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY)
+			return 0;
+	} while (get_ticks() <= etime);
 
-	/* Prevent automatic loopback of data beeing transmitted by setting
-	   ENC_PHCON2_HDLDIS */
-	phyWrite(PHY_REG_PHCON2, (1<<8));
+	printf("%s: timeout waiting for CLKRDY\n", enc->dev->name);
+	return -1;
+}
 
-	/* LEDs configuration
+/*
+ * Write the MAC address into the ENC
+ */
+static int enc_write_macaddr(enc_dev_t *enc)
+{
+	unsigned char *p = enc->dev->enetaddr;
+
+	enc_w8_retry(enc, CTL_REG_MAADR5, *p++, 5);
+	enc_w8_retry(enc, CTL_REG_MAADR4, *p++, 5);
+	enc_w8_retry(enc, CTL_REG_MAADR3, *p++, 5);
+	enc_w8_retry(enc, CTL_REG_MAADR2, *p++, 5);
+	enc_w8_retry(enc, CTL_REG_MAADR1, *p++, 5);
+	enc_w8_retry(enc, CTL_REG_MAADR0, *p, 5);
+	return 0;
+}
+
+/*
+ * Setup most of the ENC registers
+ */
+static int enc_setup(enc_dev_t *enc)
+{
+	u16 phid1 = 0;
+	u16 phid2 = 0;
+	const u16 *tp;
+
+	/* reset enc struct values */
+	enc->next_pointer = ENC_RX_BUF_START;
+	enc->rx_reset_counter = RX_RESET_COUNTER;
+	enc->bank = 0xff;	/* invalidate current bank in enc28j60 */
+
+	/* verify PHY identification */
+	phid1 = phy_read(enc, PHY_REG_PHID1);
+	phid2 = phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK;
+	if (phid1 != ENC_PHID1_VALUE || phid2 != ENC_PHID2_VALUE) {
+		printf("%s: failed to identify PHY. Found %04x:%04x\n",
+			enc->dev->name, phid1, phid2);
+		return -1;
+	}
+
+	/* now program registers */
+	for (tp = enc_initdata; *tp != 0xffff; tp += 2)
+		enc_w8_retry(enc, tp[0], tp[1], 10);
+
+	/*
+	 * Prevent automatic loopback of data beeing transmitted by setting
+	 * ENC_PHCON2_HDLDIS
+	 */
+	phy_write(enc, PHY_REG_PHCON2, (1<<8));
+
+	/*
+	 * LEDs configuration
 	 * LEDA: LACFG = 0100 -> display link status
 	 * LEDB: LBCFG = 0111 -> display TX & RX activity
 	 * STRCH = 1 -> LED pulses
 	 */
-	phyWrite(PHY_REG_PHLCON, 0x0472);
+	phy_write(enc, PHY_REG_PHLCON, 0x0472);
 
 	/* Reset PDPXMD-bit => half duplex */
-	phyWrite(PHY_REG_PHCON1, 0);
-
-	/*
-	 * Receive settings
-	 */
+	phy_write(enc, PHY_REG_PHCON1, 0);
 
 #ifdef CONFIG_USE_IRQ
 	/* enable interrupts */
-	m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE);
-	m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE);
-	m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE);
-	m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE);
-	m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
+	enc_bset(enc, CTL_REG_EIE, ENC_EIE_PKTIE);
+	enc_bset(enc, CTL_REG_EIE, ENC_EIE_TXIE);
+	enc_bset(enc, CTL_REG_EIE, ENC_EIE_RXERIE);
+	enc_bset(enc, CTL_REG_EIE, ENC_EIE_TXERIE);
+	enc_bset(enc, CTL_REG_EIE, ENC_EIE_INTIE);
 #endif
+
+	return 0;
 }
 
-/*****************************************************************************
- *
- * Description:
- *    Read PHY registers.
- *
- *    NOTE! This function will change to Bank 2.
- *
- * Params:
- *    [in] addr address of the register to read
- *
- * Returns:
- *    The value in the register
+/*
+ * Check if ENC has been initialized.
+ * If not, try to initialize it.
+ * Remember initialized state in struct.
  */
-static unsigned short phyRead (unsigned char addr)
+static int enc_initcheck(enc_dev_t *enc, const enum enc_initstate requiredstate)
 {
-	unsigned short ret = 0;
+	if (enc->initstate >= requiredstate)
+		return 0;
 
-	/* move to bank 2 */
-	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
-	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
-
-	/* write address to MIREGADR */
-	m_nic_write (CTL_REG_MIREGADR, addr);
-
-	/* set MICMD.MIIRD */
-	m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD);
-
-	/* taken from the Linux driver */
-	/* move to bank 3 */
-	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
-	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
-
-	/* poll MISTAT.BUSY bit until operation is complete */
-	while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
-		static int cnt = 0;
-
-		if (cnt++ >= 1000) {
-			/* GJ - this seems extremely dangerous! */
-			/* printf("#"); */
-			cnt = 0;
+	if (enc->initstate < setupdone) {
+		/* Initialize the ENC only */
+		enc_reset(enc);
+		/* if any of functions fails, skip the rest and return an error */
+		if (enc_clock_wait(enc) || enc_setup(enc) || enc_write_macaddr(enc)) {
+			return -1;
 		}
+		enc->initstate = setupdone;
 	}
+	/* if that's all we need, return here */
+	if (enc->initstate >= requiredstate)
+		return 0;
 
-	/* taken from the Linux driver */
-	/* move to bank 2 */
-	m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
-	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
-
-	/* clear MICMD.MIIRD */
-	m_nic_write (CTL_REG_MICMD, 0);
-
-	ret = (m_nic_read (CTL_REG_MIRDH) << 8);
-	ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF);
-
-	return ret;
+	/* now wait for link ready condition */
+	if (enc_phy_link_wait(enc)) {
+		return -1;
+	}
+	enc->initstate = linkready;
+	return 0;
 }
 
-/*****************************************************************************
+#if defined(CONFIG_CMD_MII)
+/*
+ * Read a PHY register.
  *
- * Taken from the Linux driver.
- * Description:
- * Write PHY registers.
- *
- * NOTE! This function will change to Bank 3.
- *
- * Params:
- * [in] addr address of the register to write to
- * [in] data to be written
- *
- * Returns:
- *    None
+ * This function is registered with miiphy_register().
  */
-static void phyWrite(unsigned char addr, unsigned short data)
+int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
 {
-	/* move to bank 2 */
-	m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
-	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+	struct eth_device *dev = eth_get_dev_by_name(devname);
+	enc_dev_t *enc;
 
-	/* write address to MIREGADR */
-	m_nic_write(CTL_REG_MIREGADR, addr);
+	if (!dev || phy_adr != 0)
+		return -1;
 
-	m_nic_write(CTL_REG_MIWRL, data & 0xff);
-	m_nic_write(CTL_REG_MIWRH, data >> 8);
-
-	/* move to bank 3 */
-	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
-	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
-
-	/* poll MISTAT.BUSY bit until operation is complete */
-	while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
-		static int cnt = 0;
-
-		if(cnt++ >= 1000) {
-			cnt = 0;
-		}
+	enc = dev->priv;
+	if (enc_claim_bus(enc))
+		return -1;
+	if (enc_initcheck(enc, setupdone)) {
+		enc_release_bus(enc);
+		return -1;
 	}
+	*value = phy_read(enc, reg);
+	enc_release_bus(enc);
+	return 0;
+}
+
+/*
+ * Write a PHY register.
+ *
+ * This function is registered with miiphy_register().
+ */
+int enc_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+{
+	struct eth_device *dev = eth_get_dev_by_name(devname);
+	enc_dev_t *enc;
+
+	if (!dev || phy_adr != 0)
+		return -1;
+
+	enc = dev->priv;
+	if (enc_claim_bus(enc))
+		return -1;
+	if (enc_initcheck(enc, setupdone)) {
+		enc_release_bus(enc);
+		return -1;
+	}
+	phy_write(enc, reg, value);
+	enc_release_bus(enc);
+	return 0;
+}
+#endif
+
+/*
+ * Write hardware (MAC) address.
+ *
+ * This function entered into eth_device structure.
+ */
+static int enc_write_hwaddr(struct eth_device *dev)
+{
+	enc_dev_t *enc = dev->priv;
+
+	if (enc_claim_bus(enc))
+		return -1;
+	if (enc_initcheck(enc, setupdone)) {
+		enc_release_bus(enc);
+		return -1;
+	}
+	enc_release_bus(enc);
+	return 0;
+}
+
+/*
+ * Initialize ENC28J60 for use.
+ *
+ * This function entered into eth_device structure.
+ */
+static int enc_init(struct eth_device *dev, bd_t *bis)
+{
+	enc_dev_t *enc = dev->priv;
+
+	if (enc_claim_bus(enc))
+		return -1;
+	if (enc_initcheck(enc, linkready)) {
+		enc_release_bus(enc);
+		return -1;
+	}
+	/* enable receive */
+	enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
+	enc_release_bus(enc);
+	return 0;
+}
+
+/*
+ * Check for received packets.
+ *
+ * This function entered into eth_device structure.
+ */
+static int enc_recv(struct eth_device *dev)
+{
+	enc_dev_t *enc = dev->priv;
+
+	if (enc_claim_bus(enc))
+		return -1;
+	if (enc_initcheck(enc, linkready)) {
+		enc_release_bus(enc);
+		return -1;
+	}
+	/* Check for dead receiver */
+	if (enc->rx_reset_counter > 0)
+		enc->rx_reset_counter--;
+	else
+		enc_reset_rx_call(enc);
+	enc_poll(enc);
+	enc_release_bus(enc);
+	return 0;
+}
+
+/*
+ * Send a packet.
+ *
+ * This function entered into eth_device structure.
+ *
+ * Should we wait here until we have a Link? Or shall we leave that to
+ * protocol retries?
+ */
+static int enc_send(
+	struct eth_device *dev,
+	volatile void *packet,
+	int length)
+{
+	enc_dev_t *enc = dev->priv;
+
+	if (enc_claim_bus(enc))
+		return -1;
+	if (enc_initcheck(enc, linkready)) {
+		enc_release_bus(enc);
+		return -1;
+	}
+	/* setup transmit pointers */
+	enc_w16(enc, CTL_REG_EWRPTL, ENC_TX_BUF_START);
+	enc_w16(enc, CTL_REG_ETXNDL, length + ENC_TX_BUF_START);
+	enc_w16(enc, CTL_REG_ETXSTL, ENC_TX_BUF_START);
+	/* write packet to ENC */
+	enc_wbuf(enc, length, (u8 *) packet, 0x00);
+	/*
+	 * Check that the internal transmit logic has not been altered
+	 * by excessive collisions. Reset transmitter if so.
+	 * See Errata B4 12 and 14.
+	 */
+	if (enc_r8(enc, CTL_REG_EIR) & ENC_EIR_TXERIF) {
+		enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_TXRST);
+		enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_TXRST);
+	}
+	enc_bclr(enc, CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF));
+	/* start transmitting */
+	enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_TXRTS);
+	enc_release_bus(enc);
+	return 0;
+}
+
+/*
+ * Finish use of ENC.
+ *
+ * This function entered into eth_device structure.
+ */
+static void enc_halt(struct eth_device *dev)
+{
+	enc_dev_t *enc = dev->priv;
+
+	if (enc_claim_bus(enc))
+		return;
+	/* Just disable receiver */
+	enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
+	enc_release_bus(enc);
+}
+
+/*
+ * This is the only exported function.
+ *
+ * It may be called several times with different bus:cs combinations.
+ */
+int enc28j60_initialize(unsigned int bus, unsigned int cs,
+	unsigned int max_hz, unsigned int mode)
+{
+	struct eth_device *dev;
+	enc_dev_t *enc;
+
+	/* try to allocate, check and clear eth_device object */
+	dev = malloc(sizeof(*dev));
+	if (!dev) {
+		return -1;
+	}
+	memset(dev, 0, sizeof(*dev));
+
+	/* try to allocate, check and clear enc_dev_t object */
+	enc = malloc(sizeof(*enc));
+	if (!enc) {
+		free(dev);
+		return -1;
+	}
+	memset(enc, 0, sizeof(*enc));
+
+	/* try to setup the SPI slave */
+	enc->slave = spi_setup_slave(bus, cs, max_hz, mode);
+	if (!enc->slave) {
+		printf("enc28j60: invalid SPI device %i:%i\n", bus, cs);
+		free(enc);
+		free(dev);
+		return -1;
+	}
+
+	enc->dev = dev;
+	/* now fill the eth_device object */
+	dev->priv = enc;
+	dev->init = enc_init;
+	dev->halt = enc_halt;
+	dev->send = enc_send;
+	dev->recv = enc_recv;
+	dev->write_hwaddr = enc_write_hwaddr;
+	sprintf(dev->name, "enc%i.%i", bus, cs);
+	eth_register(dev);
+#if defined(CONFIG_CMD_MII)
+	miiphy_register(dev->name, enc_miiphy_read, enc_miiphy_write);
+#endif
+	return 0;
 }
diff --git a/drivers/net/enc28j60.h b/drivers/net/enc28j60.h
new file mode 100644
index 0000000..888c599
--- /dev/null
+++ b/drivers/net/enc28j60.h
@@ -0,0 +1,251 @@
+/*
+ * (X) extracted from enc28j60.c
+ * Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _enc28j60_h
+#define _enc28j60_h
+
+/*
+ * SPI Commands
+ *
+ * Bits 7-5: Command
+ * Bits 4-0: Register
+ */
+#define CMD_RCR(x)	(0x00+((x)&0x1f))	/* Read Control Register */
+#define CMD_RBM		0x3a			/* Read Buffer Memory */
+#define CMD_WCR(x)	(0x40+((x)&0x1f))	/* Write Control Register */
+#define CMD_WBM		0x7a			/* Write Buffer Memory */
+#define CMD_BFS(x)	(0x80+((x)&0x1f))	/* Bit Field Set */
+#define CMD_BFC(x)	(0xa0+((x)&0x1f))	/* Bit Field Clear */
+#define CMD_SRC		0xff			/* System Reset Command */
+
+/* NEW: encode (bank number+1) in upper byte */
+
+/* Common Control Registers accessible in all Banks */
+#define CTL_REG_EIE		0x01B
+#define CTL_REG_EIR		0x01C
+#define CTL_REG_ESTAT		0x01D
+#define CTL_REG_ECON2		0x01E
+#define CTL_REG_ECON1		0x01F
+
+/* Control Registers accessible in Bank 0 */
+#define CTL_REG_ERDPTL		0x100
+#define CTL_REG_ERDPTH		0x101
+#define CTL_REG_EWRPTL		0x102
+#define CTL_REG_EWRPTH		0x103
+#define CTL_REG_ETXSTL		0x104
+#define CTL_REG_ETXSTH		0x105
+#define CTL_REG_ETXNDL		0x106
+#define CTL_REG_ETXNDH		0x107
+#define CTL_REG_ERXSTL		0x108
+#define CTL_REG_ERXSTH		0x109
+#define CTL_REG_ERXNDL		0x10A
+#define CTL_REG_ERXNDH		0x10B
+#define CTL_REG_ERXRDPTL	0x10C
+#define CTL_REG_ERXRDPTH	0x10D
+#define CTL_REG_ERXWRPTL	0x10E
+#define CTL_REG_ERXWRPTH	0x10F
+#define CTL_REG_EDMASTL		0x110
+#define CTL_REG_EDMASTH		0x111
+#define CTL_REG_EDMANDL		0x112
+#define CTL_REG_EDMANDH		0x113
+#define CTL_REG_EDMADSTL	0x114
+#define CTL_REG_EDMADSTH	0x115
+#define CTL_REG_EDMACSL		0x116
+#define CTL_REG_EDMACSH		0x117
+
+/* Control Registers accessible in Bank 1 */
+#define CTL_REG_EHT0		0x200
+#define CTL_REG_EHT1		0x201
+#define CTL_REG_EHT2		0x202
+#define CTL_REG_EHT3		0x203
+#define CTL_REG_EHT4		0x204
+#define CTL_REG_EHT5		0x205
+#define CTL_REG_EHT6		0x206
+#define CTL_REG_EHT7		0x207
+#define CTL_REG_EPMM0		0x208
+#define CTL_REG_EPMM1		0x209
+#define CTL_REG_EPMM2		0x20A
+#define CTL_REG_EPMM3		0x20B
+#define CTL_REG_EPMM4		0x20C
+#define CTL_REG_EPMM5		0x20D
+#define CTL_REG_EPMM6		0x20E
+#define CTL_REG_EPMM7		0x20F
+#define CTL_REG_EPMCSL		0x210
+#define CTL_REG_EPMCSH		0x211
+#define CTL_REG_EPMOL		0x214
+#define CTL_REG_EPMOH		0x215
+#define CTL_REG_EWOLIE		0x216
+#define CTL_REG_EWOLIR		0x217
+#define CTL_REG_ERXFCON		0x218
+#define CTL_REG_EPKTCNT		0x219
+
+/* Control Registers accessible in Bank 2 */
+#define CTL_REG_MACON1		0x300
+#define CTL_REG_MACON2		0x301
+#define CTL_REG_MACON3		0x302
+#define CTL_REG_MACON4		0x303
+#define CTL_REG_MABBIPG		0x304
+#define CTL_REG_MAIPGL		0x306
+#define CTL_REG_MAIPGH		0x307
+#define CTL_REG_MACLCON1	0x308
+#define CTL_REG_MACLCON2	0x309
+#define CTL_REG_MAMXFLL		0x30A
+#define CTL_REG_MAMXFLH		0x30B
+#define CTL_REG_MAPHSUP		0x30D
+#define CTL_REG_MICON		0x311
+#define CTL_REG_MICMD		0x312
+#define CTL_REG_MIREGADR	0x314
+#define CTL_REG_MIWRL		0x316
+#define CTL_REG_MIWRH		0x317
+#define CTL_REG_MIRDL		0x318
+#define CTL_REG_MIRDH		0x319
+
+/* Control Registers accessible in Bank 3 */
+#define CTL_REG_MAADR1		0x400
+#define CTL_REG_MAADR0		0x401
+#define CTL_REG_MAADR3		0x402
+#define CTL_REG_MAADR2		0x403
+#define CTL_REG_MAADR5		0x404
+#define CTL_REG_MAADR4		0x405
+#define CTL_REG_EBSTSD		0x406
+#define CTL_REG_EBSTCON		0x407
+#define CTL_REG_EBSTCSL		0x408
+#define CTL_REG_EBSTCSH		0x409
+#define CTL_REG_MISTAT		0x40A
+#define CTL_REG_EREVID		0x412
+#define CTL_REG_ECOCON		0x415
+#define CTL_REG_EFLOCON		0x417
+#define CTL_REG_EPAUSL		0x418
+#define CTL_REG_EPAUSH		0x419
+
+/* PHY Register */
+#define PHY_REG_PHCON1		0x00
+#define PHY_REG_PHSTAT1		0x01
+#define PHY_REG_PHID1		0x02
+#define PHY_REG_PHID2		0x03
+#define PHY_REG_PHCON2		0x10
+#define PHY_REG_PHSTAT2		0x11
+#define PHY_REG_PHLCON		0x14
+
+/* Receive Filter Register (ERXFCON) bits */
+#define ENC_RFR_UCEN		0x80
+#define ENC_RFR_ANDOR		0x40
+#define ENC_RFR_CRCEN		0x20
+#define ENC_RFR_PMEN		0x10
+#define ENC_RFR_MPEN		0x08
+#define ENC_RFR_HTEN		0x04
+#define ENC_RFR_MCEN		0x02
+#define ENC_RFR_BCEN		0x01
+
+/* ECON1 Register Bits */
+#define ENC_ECON1_TXRST		0x80
+#define ENC_ECON1_RXRST		0x40
+#define ENC_ECON1_DMAST		0x20
+#define ENC_ECON1_CSUMEN	0x10
+#define ENC_ECON1_TXRTS		0x08
+#define ENC_ECON1_RXEN		0x04
+#define ENC_ECON1_BSEL1		0x02
+#define ENC_ECON1_BSEL0		0x01
+
+/* ECON2 Register Bits */
+#define ENC_ECON2_AUTOINC	0x80
+#define ENC_ECON2_PKTDEC	0x40
+#define ENC_ECON2_PWRSV		0x20
+#define ENC_ECON2_VRPS		0x08
+
+/* EIR Register Bits */
+#define ENC_EIR_PKTIF		0x40
+#define ENC_EIR_DMAIF		0x20
+#define ENC_EIR_LINKIF		0x10
+#define ENC_EIR_TXIF		0x08
+#define ENC_EIR_WOLIF		0x04
+#define ENC_EIR_TXERIF		0x02
+#define ENC_EIR_RXERIF		0x01
+
+/* ESTAT Register Bits */
+#define ENC_ESTAT_INT		0x80
+#define ENC_ESTAT_LATECOL	0x10
+#define ENC_ESTAT_RXBUSY	0x04
+#define ENC_ESTAT_TXABRT	0x02
+#define ENC_ESTAT_CLKRDY	0x01
+
+/* EIE Register Bits */
+#define ENC_EIE_INTIE		0x80
+#define ENC_EIE_PKTIE		0x40
+#define ENC_EIE_DMAIE		0x20
+#define ENC_EIE_LINKIE		0x10
+#define ENC_EIE_TXIE		0x08
+#define ENC_EIE_WOLIE		0x04
+#define ENC_EIE_TXERIE		0x02
+#define ENC_EIE_RXERIE		0x01
+
+/* MACON1 Register Bits */
+#define ENC_MACON1_LOOPBK	0x10
+#define ENC_MACON1_TXPAUS	0x08
+#define ENC_MACON1_RXPAUS	0x04
+#define ENC_MACON1_PASSALL	0x02
+#define ENC_MACON1_MARXEN	0x01
+
+/* MACON2 Register Bits */
+#define ENC_MACON2_MARST	0x80
+#define ENC_MACON2_RNDRST	0x40
+#define ENC_MACON2_MARXRST	0x08
+#define ENC_MACON2_RFUNRST	0x04
+#define ENC_MACON2_MATXRST	0x02
+#define ENC_MACON2_TFUNRST	0x01
+
+/* MACON3 Register Bits */
+#define ENC_MACON3_PADCFG2	0x80
+#define ENC_MACON3_PADCFG1	0x40
+#define ENC_MACON3_PADCFG0	0x20
+#define ENC_MACON3_TXCRCEN	0x10
+#define ENC_MACON3_PHDRLEN	0x08
+#define ENC_MACON3_HFRMEN	0x04
+#define ENC_MACON3_FRMLNEN	0x02
+#define ENC_MACON3_FULDPX	0x01
+
+/* MACON4 Register Bits */
+#define ENC_MACON4_DEFER	0x40
+
+/* MICMD Register Bits */
+#define ENC_MICMD_MIISCAN	0x02
+#define ENC_MICMD_MIIRD		0x01
+
+/* MISTAT Register Bits */
+#define ENC_MISTAT_NVALID	0x04
+#define ENC_MISTAT_SCAN		0x02
+#define ENC_MISTAT_BUSY		0x01
+
+/* PHID1 and PHID2 values */
+#define ENC_PHID1_VALUE		0x0083
+#define ENC_PHID2_VALUE		0x1400
+#define ENC_PHID2_MASK		0xFC00
+
+/* PHCON1 values */
+#define	ENC_PHCON1_PDPXMD	0x0100
+
+/* PHSTAT1 values */
+#define	ENC_PHSTAT1_LLSTAT	0x0004
+
+/* PHSTAT2 values */
+#define	ENC_PHSTAT2_LSTAT	0x0400
+#define	ENC_PHSTAT2_DPXSTAT	0x0200
+
+#endif
diff --git a/drivers/net/enc28j60_lpc2292.c b/drivers/net/enc28j60_lpc2292.c
new file mode 100644
index 0000000..bf95052
--- /dev/null
+++ b/drivers/net/enc28j60_lpc2292.c
@@ -0,0 +1,983 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#warning This driver is depreciated. Please update to new SPI framework enc28j60 driver
+#include <config.h>
+#include <common.h>
+#include <net.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/spi.h>
+
+/*
+ * Control Registers in Bank 0
+ */
+
+#define CTL_REG_ERDPTL	 0x00
+#define CTL_REG_ERDPTH	 0x01
+#define CTL_REG_EWRPTL	 0x02
+#define CTL_REG_EWRPTH	 0x03
+#define CTL_REG_ETXSTL	 0x04
+#define CTL_REG_ETXSTH	 0x05
+#define CTL_REG_ETXNDL	 0x06
+#define CTL_REG_ETXNDH	 0x07
+#define CTL_REG_ERXSTL	 0x08
+#define CTL_REG_ERXSTH	 0x09
+#define CTL_REG_ERXNDL	 0x0A
+#define CTL_REG_ERXNDH	 0x0B
+#define CTL_REG_ERXRDPTL 0x0C
+#define CTL_REG_ERXRDPTH 0x0D
+#define CTL_REG_ERXWRPTL 0x0E
+#define CTL_REG_ERXWRPTH 0x0F
+#define CTL_REG_EDMASTL  0x10
+#define CTL_REG_EDMASTH  0x11
+#define CTL_REG_EDMANDL  0x12
+#define CTL_REG_EDMANDH  0x13
+#define CTL_REG_EDMADSTL 0x14
+#define CTL_REG_EDMADSTH 0x15
+#define CTL_REG_EDMACSL  0x16
+#define CTL_REG_EDMACSH  0x17
+/* these are common in all banks */
+#define CTL_REG_EIE	 0x1B
+#define CTL_REG_EIR	 0x1C
+#define CTL_REG_ESTAT	 0x1D
+#define CTL_REG_ECON2	 0x1E
+#define CTL_REG_ECON1	 0x1F
+
+/*
+ * Control Registers in Bank 1
+ */
+
+#define CTL_REG_EHT0	0x00
+#define CTL_REG_EHT1	0x01
+#define CTL_REG_EHT2	0x02
+#define CTL_REG_EHT3	0x03
+#define CTL_REG_EHT4	0x04
+#define CTL_REG_EHT5	0x05
+#define CTL_REG_EHT6	0x06
+#define CTL_REG_EHT7	0x07
+#define CTL_REG_EPMM0	0x08
+#define CTL_REG_EPMM1	0x09
+#define CTL_REG_EPMM2	0x0A
+#define CTL_REG_EPMM3	0x0B
+#define CTL_REG_EPMM4	0x0C
+#define CTL_REG_EPMM5	0x0D
+#define CTL_REG_EPMM6	0x0E
+#define CTL_REG_EPMM7	0x0F
+#define CTL_REG_EPMCSL	0x10
+#define CTL_REG_EPMCSH	0x11
+#define CTL_REG_EPMOL	0x14
+#define CTL_REG_EPMOH	0x15
+#define CTL_REG_EWOLIE	0x16
+#define CTL_REG_EWOLIR	0x17
+#define CTL_REG_ERXFCON 0x18
+#define CTL_REG_EPKTCNT 0x19
+
+/*
+ * Control Registers in Bank 2
+ */
+
+#define CTL_REG_MACON1	 0x00
+#define CTL_REG_MACON2	 0x01
+#define CTL_REG_MACON3	 0x02
+#define CTL_REG_MACON4	 0x03
+#define CTL_REG_MABBIPG  0x04
+#define CTL_REG_MAIPGL	 0x06
+#define CTL_REG_MAIPGH	 0x07
+#define CTL_REG_MACLCON1 0x08
+#define CTL_REG_MACLCON2 0x09
+#define CTL_REG_MAMXFLL  0x0A
+#define CTL_REG_MAMXFLH  0x0B
+#define CTL_REG_MAPHSUP  0x0D
+#define CTL_REG_MICON	 0x11
+#define CTL_REG_MICMD	 0x12
+#define CTL_REG_MIREGADR 0x14
+#define CTL_REG_MIWRL	 0x16
+#define CTL_REG_MIWRH	 0x17
+#define CTL_REG_MIRDL	 0x18
+#define CTL_REG_MIRDH	 0x19
+
+/*
+ * Control Registers in Bank 3
+ */
+
+#define CTL_REG_MAADR1	0x00
+#define CTL_REG_MAADR0	0x01
+#define CTL_REG_MAADR3	0x02
+#define CTL_REG_MAADR2	0x03
+#define CTL_REG_MAADR5	0x04
+#define CTL_REG_MAADR4	0x05
+#define CTL_REG_EBSTSD	0x06
+#define CTL_REG_EBSTCON 0x07
+#define CTL_REG_EBSTCSL 0x08
+#define CTL_REG_EBSTCSH 0x09
+#define CTL_REG_MISTAT	0x0A
+#define CTL_REG_EREVID	0x12
+#define CTL_REG_ECOCON	0x15
+#define CTL_REG_EFLOCON 0x17
+#define CTL_REG_EPAUSL	0x18
+#define CTL_REG_EPAUSH	0x19
+
+
+/*
+ * PHY Register
+ */
+
+#define PHY_REG_PHID1 0x02
+#define PHY_REG_PHID2 0x03
+/* taken from the Linux driver */
+#define PHY_REG_PHCON1 0x00
+#define PHY_REG_PHCON2 0x10
+#define PHY_REG_PHLCON 0x14
+
+/*
+ * Receive Filter Register (ERXFCON) bits
+ */
+
+#define ENC_RFR_UCEN  0x80
+#define ENC_RFR_ANDOR 0x40
+#define ENC_RFR_CRCEN 0x20
+#define ENC_RFR_PMEN  0x10
+#define ENC_RFR_MPEN  0x08
+#define ENC_RFR_HTEN  0x04
+#define ENC_RFR_MCEN  0x02
+#define ENC_RFR_BCEN  0x01
+
+/*
+ * ECON1 Register Bits
+ */
+
+#define ENC_ECON1_TXRST  0x80
+#define ENC_ECON1_RXRST  0x40
+#define ENC_ECON1_DMAST  0x20
+#define ENC_ECON1_CSUMEN 0x10
+#define ENC_ECON1_TXRTS  0x08
+#define ENC_ECON1_RXEN	 0x04
+#define ENC_ECON1_BSEL1  0x02
+#define ENC_ECON1_BSEL0  0x01
+
+/*
+ * ECON2 Register Bits
+ */
+#define ENC_ECON2_AUTOINC 0x80
+#define ENC_ECON2_PKTDEC  0x40
+#define ENC_ECON2_PWRSV   0x20
+#define ENC_ECON2_VRPS	  0x08
+
+/*
+ * EIR Register Bits
+ */
+#define ENC_EIR_PKTIF  0x40
+#define ENC_EIR_DMAIF  0x20
+#define ENC_EIR_LINKIF 0x10
+#define ENC_EIR_TXIF   0x08
+#define ENC_EIR_WOLIF  0x04
+#define ENC_EIR_TXERIF 0x02
+#define ENC_EIR_RXERIF 0x01
+
+/*
+ * ESTAT Register Bits
+ */
+
+#define ENC_ESTAT_INT	  0x80
+#define ENC_ESTAT_LATECOL 0x10
+#define ENC_ESTAT_RXBUSY  0x04
+#define ENC_ESTAT_TXABRT  0x02
+#define ENC_ESTAT_CLKRDY  0x01
+
+/*
+ * EIE Register Bits
+ */
+
+#define ENC_EIE_INTIE  0x80
+#define ENC_EIE_PKTIE  0x40
+#define ENC_EIE_DMAIE  0x20
+#define ENC_EIE_LINKIE 0x10
+#define ENC_EIE_TXIE   0x08
+#define ENC_EIE_WOLIE  0x04
+#define ENC_EIE_TXERIE 0x02
+#define ENC_EIE_RXERIE 0x01
+
+/*
+ * MACON1 Register Bits
+ */
+#define ENC_MACON1_LOOPBK  0x10
+#define ENC_MACON1_TXPAUS  0x08
+#define ENC_MACON1_RXPAUS  0x04
+#define ENC_MACON1_PASSALL 0x02
+#define ENC_MACON1_MARXEN  0x01
+
+
+/*
+ * MACON2 Register Bits
+ */
+#define ENC_MACON2_MARST   0x80
+#define ENC_MACON2_RNDRST  0x40
+#define ENC_MACON2_MARXRST 0x08
+#define ENC_MACON2_RFUNRST 0x04
+#define ENC_MACON2_MATXRST 0x02
+#define ENC_MACON2_TFUNRST 0x01
+
+/*
+ * MACON3 Register Bits
+ */
+#define ENC_MACON3_PADCFG2 0x80
+#define ENC_MACON3_PADCFG1 0x40
+#define ENC_MACON3_PADCFG0 0x20
+#define ENC_MACON3_TXCRCEN 0x10
+#define ENC_MACON3_PHDRLEN 0x08
+#define ENC_MACON3_HFRMEN  0x04
+#define ENC_MACON3_FRMLNEN 0x02
+#define ENC_MACON3_FULDPX  0x01
+
+/*
+ * MICMD Register Bits
+ */
+#define ENC_MICMD_MIISCAN 0x02
+#define ENC_MICMD_MIIRD   0x01
+
+/*
+ * MISTAT Register Bits
+ */
+#define ENC_MISTAT_NVALID 0x04
+#define ENC_MISTAT_SCAN   0x02
+#define ENC_MISTAT_BUSY   0x01
+
+/*
+ * PHID1 and PHID2 values
+ */
+#define ENC_PHID1_VALUE 0x0083
+#define ENC_PHID2_VALUE 0x1400
+#define ENC_PHID2_MASK	0xFC00
+
+
+#define ENC_SPI_SLAVE_CS 0x00010000	/* pin P1.16 */
+#define ENC_RESET	 0x00020000	/* pin P1.17 */
+
+#define FAILSAFE_VALUE 5000
+
+/*
+ * Controller memory layout:
+ *
+ * 0x0000 - 0x17ff  6k bytes receive buffer
+ * 0x1800 - 0x1fff  2k bytes transmit buffer
+ */
+/* Use the lower memory for receiver buffer. See errata pt. 5 */
+#define ENC_RX_BUF_START 0x0000
+#define ENC_TX_BUF_START 0x1800
+/* taken from the Linux driver */
+#define ENC_RX_BUF_END   0x17ff
+#define ENC_TX_BUF_END   0x1fff
+
+/* maximum frame length */
+#define ENC_MAX_FRM_LEN 1518
+
+#define enc_enable() PUT32(IO1CLR, ENC_SPI_SLAVE_CS)
+#define enc_disable() PUT32(IO1SET, ENC_SPI_SLAVE_CS)
+#define enc_cfg_spi() spi_set_cfg(0, 0, 0); spi_set_clock(8);
+
+
+static unsigned char encReadReg (unsigned char regNo);
+static void encWriteReg (unsigned char regNo, unsigned char data);
+static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c);
+static void encReadBuff (unsigned short length, unsigned char *pBuff);
+static void encWriteBuff (unsigned short length, unsigned char *pBuff);
+static void encBitSet (unsigned char regNo, unsigned char data);
+static void encBitClr (unsigned char regNo, unsigned char data);
+static void encReset (void);
+static void encInit (unsigned char *pEthAddr);
+static unsigned short phyRead (unsigned char addr);
+static void phyWrite(unsigned char, unsigned short);
+static void encPoll (void);
+static void encRx (void);
+
+#define m_nic_read(reg) encReadReg(reg)
+#define m_nic_write(reg, data) encWriteReg(reg, data)
+#define m_nic_write_retry(reg, data, count) encWriteRegRetry(reg, data, count)
+#define m_nic_read_data(len, buf) encReadBuff((len), (buf))
+#define m_nic_write_data(len, buf) encWriteBuff((len), (buf))
+
+/* bit field set */
+#define m_nic_bfs(reg, data) encBitSet(reg, data)
+
+/* bit field clear */
+#define m_nic_bfc(reg, data) encBitClr(reg, data)
+
+static unsigned char bank = 0;	/* current bank in enc28j60 */
+static unsigned char next_pointer_lsb;
+static unsigned char next_pointer_msb;
+
+static unsigned char buffer[ENC_MAX_FRM_LEN];
+static int rxResetCounter = 0;
+
+#define RX_RESET_COUNTER 1000;
+
+/*-----------------------------------------------------------------------------
+ * Always returns 0
+ */
+int eth_init (bd_t * bis)
+{
+	unsigned char estatVal;
+	uchar enetaddr[6];
+
+	/* configure GPIO */
+	(*((volatile unsigned long *) IO1DIR)) |= ENC_SPI_SLAVE_CS;
+	(*((volatile unsigned long *) IO1DIR)) |= ENC_RESET;
+
+	/* CS and RESET active low */
+	PUT32 (IO1SET, ENC_SPI_SLAVE_CS);
+	PUT32 (IO1SET, ENC_RESET);
+
+	spi_init ();
+
+	/* taken from the Linux driver - dangerous stuff here! */
+	/* Wait for CLKRDY to become set (i.e., check that we can communicate with
+	   the ENC) */
+	do
+	{
+		estatVal = m_nic_read(CTL_REG_ESTAT);
+	} while ((estatVal & 0x08) || (~estatVal & ENC_ESTAT_CLKRDY));
+
+	/* initialize controller */
+	encReset ();
+	eth_getenv_enetaddr("ethaddr", enetaddr);
+	encInit (enetaddr);
+
+	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN);	/* enable receive */
+
+	return 0;
+}
+
+int eth_send (volatile void *packet, int length)
+{
+	/* check frame length, etc. */
+	/* TODO: */
+
+	/* switch to bank 0 */
+	m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+	/* set EWRPT */
+	m_nic_write (CTL_REG_EWRPTL, (ENC_TX_BUF_START & 0xff));
+	m_nic_write (CTL_REG_EWRPTH, (ENC_TX_BUF_START >> 8));
+
+	/* set ETXND */
+	m_nic_write (CTL_REG_ETXNDL, (length + ENC_TX_BUF_START) & 0xFF);
+	m_nic_write (CTL_REG_ETXNDH, (length + ENC_TX_BUF_START) >> 8);
+
+	/* set ETXST */
+	m_nic_write (CTL_REG_ETXSTL, ENC_TX_BUF_START & 0xFF);
+	m_nic_write (CTL_REG_ETXSTH, ENC_TX_BUF_START >> 8);
+
+	/* write packet */
+	m_nic_write_data (length, (unsigned char *) packet);
+
+	/* taken from the Linux driver */
+	/* Verify that the internal transmit logic has not been altered by excessive
+	   collisions.  See Errata B4 12 and 14.
+	 */
+	if (m_nic_read(CTL_REG_EIR) & ENC_EIR_TXERIF) {
+		m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_TXRST);
+		m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_TXRST);
+	}
+	m_nic_bfc(CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF));
+
+	/* set ECON1.TXRTS */
+	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_TXRTS);
+
+	return 0;
+}
+
+
+/*****************************************************************************
+ * This function resets the receiver only. This function may be called from
+ * interrupt-context.
+ */
+static void encReceiverReset (void)
+{
+	unsigned char econ1;
+
+	econ1 = m_nic_read (CTL_REG_ECON1);
+	if ((econ1 & ENC_ECON1_RXRST) == 0) {
+		m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXRST);
+		rxResetCounter = RX_RESET_COUNTER;
+	}
+}
+
+/*****************************************************************************
+ * receiver reset timer
+ */
+static void encReceiverResetCallback (void)
+{
+	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXRST);
+	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_RXEN);	/* enable receive */
+}
+
+/*-----------------------------------------------------------------------------
+ * Check for received packets. Call NetReceive for each packet. The return
+ * value is ignored by the caller.
+ */
+int eth_rx (void)
+{
+	if (rxResetCounter > 0 && --rxResetCounter == 0) {
+		encReceiverResetCallback ();
+	}
+
+	encPoll ();
+
+	return 0;
+}
+
+void eth_halt (void)
+{
+	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_RXEN);	/* disable receive */
+}
+
+/*****************************************************************************/
+
+static void encPoll (void)
+{
+	unsigned char eir_reg;
+	volatile unsigned char estat_reg;
+	unsigned char pkt_cnt;
+
+#ifdef CONFIG_USE_IRQ
+	/* clear global interrupt enable bit in enc28j60 */
+	m_nic_bfc (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+	estat_reg = m_nic_read (CTL_REG_ESTAT);
+
+	eir_reg = m_nic_read (CTL_REG_EIR);
+
+	if (eir_reg & ENC_EIR_TXIF) {
+		/* clear TXIF bit in EIR */
+		m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXIF);
+	}
+
+	/* We have to use pktcnt and not pktif bit, see errata pt. 6 */
+
+	/* move to bank 1 */
+	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+	/* read pktcnt */
+	pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
+
+	if (pkt_cnt > 0) {
+		if ((eir_reg & ENC_EIR_PKTIF) == 0) {
+			/*printf("encPoll: pkt cnt > 0, but pktif not set\n"); */
+		}
+		encRx ();
+		/* clear PKTIF bit in EIR, this should not need to be done but it
+		   seems like we get problems if we do not */
+		m_nic_bfc (CTL_REG_EIR, ENC_EIR_PKTIF);
+	}
+
+	if (eir_reg & ENC_EIR_RXERIF) {
+		printf ("encPoll: rx error\n");
+		m_nic_bfc (CTL_REG_EIR, ENC_EIR_RXERIF);
+	}
+	if (eir_reg & ENC_EIR_TXERIF) {
+		printf ("encPoll: tx error\n");
+		m_nic_bfc (CTL_REG_EIR, ENC_EIR_TXERIF);
+	}
+
+#ifdef CONFIG_USE_IRQ
+	/* set global interrupt enable bit in enc28j60 */
+	m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+}
+
+static void encRx (void)
+{
+	unsigned short pkt_len;
+	unsigned short copy_len;
+	unsigned short status;
+	unsigned char eir_reg;
+	unsigned char pkt_cnt = 0;
+	unsigned short rxbuf_rdpt;
+
+	/* switch to bank 0 */
+	m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+	m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
+	m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
+
+	do {
+		m_nic_read_data (6, buffer);
+		next_pointer_lsb = buffer[0];
+		next_pointer_msb = buffer[1];
+		pkt_len = buffer[2];
+		pkt_len |= (unsigned short) buffer[3] << 8;
+		status = buffer[4];
+		status |= (unsigned short) buffer[5] << 8;
+
+		if (pkt_len <= ENC_MAX_FRM_LEN)
+			copy_len = pkt_len;
+		else
+			copy_len = 0;
+
+		if ((status & (1L << 7)) == 0) /* check Received Ok bit */
+			copy_len = 0;
+
+		/* taken from the Linux driver */
+		/* check if next pointer is resonable */
+		if ((((unsigned int)next_pointer_msb << 8) |
+			(unsigned int)next_pointer_lsb) >= ENC_TX_BUF_START)
+			copy_len = 0;
+
+		if (copy_len > 0) {
+			m_nic_read_data (copy_len, buffer);
+		}
+
+		/* advance read pointer to next pointer */
+		m_nic_write (CTL_REG_ERDPTL, next_pointer_lsb);
+		m_nic_write (CTL_REG_ERDPTH, next_pointer_msb);
+
+		/* decrease packet counter */
+		m_nic_bfs (CTL_REG_ECON2, ENC_ECON2_PKTDEC);
+
+		/* taken from the Linux driver */
+		/* Only odd values should be written to ERXRDPTL,
+		 * see errata B4 pt.13
+		 */
+		rxbuf_rdpt = (next_pointer_msb << 8 | next_pointer_lsb) - 1;
+		if ((rxbuf_rdpt < (m_nic_read(CTL_REG_ERXSTH) << 8 |
+				m_nic_read(CTL_REG_ERXSTL))) || (rxbuf_rdpt >
+				(m_nic_read(CTL_REG_ERXNDH) << 8 |
+				m_nic_read(CTL_REG_ERXNDL)))) {
+			m_nic_write(CTL_REG_ERXRDPTL, m_nic_read(CTL_REG_ERXNDL));
+			m_nic_write(CTL_REG_ERXRDPTH, m_nic_read(CTL_REG_ERXNDH));
+		} else {
+			m_nic_write(CTL_REG_ERXRDPTL, rxbuf_rdpt & 0xFF);
+			m_nic_write(CTL_REG_ERXRDPTH, rxbuf_rdpt >> 8);
+		}
+
+		/* move to bank 1 */
+		m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+		m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+
+		/* read pktcnt */
+		pkt_cnt = m_nic_read (CTL_REG_EPKTCNT);
+
+		/* switch to bank 0 */
+		m_nic_bfc (CTL_REG_ECON1,
+			   (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+		if (copy_len == 0) {
+			eir_reg = m_nic_read (CTL_REG_EIR);
+			encReceiverReset ();
+			printf ("eth_rx: copy_len=0\n");
+			continue;
+		}
+
+		NetReceive ((unsigned char *) buffer, pkt_len);
+
+		eir_reg = m_nic_read (CTL_REG_EIR);
+	} while (pkt_cnt);	/* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
+}
+
+static void encWriteReg (unsigned char regNo, unsigned char data)
+{
+	spi_lock ();
+	enc_cfg_spi ();
+	enc_enable ();
+
+	spi_write (0x40 | regNo);	/* write in regNo */
+	spi_write (data);
+
+	enc_disable ();
+	enc_enable ();
+
+	spi_write (0x1f);	/* write reg 0x1f */
+
+	enc_disable ();
+	spi_unlock ();
+}
+
+static void encWriteRegRetry (unsigned char regNo, unsigned char data, int c)
+{
+	unsigned char readback;
+	int i;
+
+	spi_lock ();
+
+	for (i = 0; i < c; i++) {
+		enc_cfg_spi ();
+		enc_enable ();
+
+		spi_write (0x40 | regNo);	/* write in regNo */
+		spi_write (data);
+
+		enc_disable ();
+		enc_enable ();
+
+		spi_write (0x1f);	/* write reg 0x1f */
+
+		enc_disable ();
+
+		spi_unlock ();	/* we must unlock spi first */
+
+		readback = encReadReg (regNo);
+
+		spi_lock ();
+
+		if (readback == data)
+			break;
+	}
+	spi_unlock ();
+
+	if (i == c) {
+		printf ("enc28j60: write reg %d failed\n", regNo);
+	}
+}
+
+static unsigned char encReadReg (unsigned char regNo)
+{
+	unsigned char rxByte;
+
+	spi_lock ();
+	enc_cfg_spi ();
+	enc_enable ();
+
+	spi_write (0x1f);	/* read reg 0x1f */
+
+	bank = spi_read () & 0x3;
+
+	enc_disable ();
+	enc_enable ();
+
+	spi_write (regNo);
+	rxByte = spi_read ();
+
+	/* check if MAC or MII register */
+	if (((bank == 2) && (regNo <= 0x1a)) ||
+	    ((bank == 3) && (regNo <= 0x05 || regNo == 0x0a))) {
+		/* ignore first byte and read another byte */
+		rxByte = spi_read ();
+	}
+
+	enc_disable ();
+	spi_unlock ();
+
+	return rxByte;
+}
+
+static void encReadBuff (unsigned short length, unsigned char *pBuff)
+{
+	spi_lock ();
+	enc_cfg_spi ();
+	enc_enable ();
+
+	spi_write (0x20 | 0x1a);	/* read buffer memory */
+
+	while (length--) {
+		if (pBuff != NULL)
+			*pBuff++ = spi_read ();
+		else
+			spi_write (0);
+	}
+
+	enc_disable ();
+	spi_unlock ();
+}
+
+static void encWriteBuff (unsigned short length, unsigned char *pBuff)
+{
+	spi_lock ();
+	enc_cfg_spi ();
+	enc_enable ();
+
+	spi_write (0x60 | 0x1a);	/* write buffer memory */
+
+	spi_write (0x00);	/* control byte */
+
+	while (length--)
+		spi_write (*pBuff++);
+
+	enc_disable ();
+	spi_unlock ();
+}
+
+static void encBitSet (unsigned char regNo, unsigned char data)
+{
+	spi_lock ();
+	enc_cfg_spi ();
+	enc_enable ();
+
+	spi_write (0x80 | regNo);	/* bit field set */
+	spi_write (data);
+
+	enc_disable ();
+	spi_unlock ();
+}
+
+static void encBitClr (unsigned char regNo, unsigned char data)
+{
+	spi_lock ();
+	enc_cfg_spi ();
+	enc_enable ();
+
+	spi_write (0xA0 | regNo);	/* bit field clear */
+	spi_write (data);
+
+	enc_disable ();
+	spi_unlock ();
+}
+
+static void encReset (void)
+{
+	spi_lock ();
+	enc_cfg_spi ();
+	enc_enable ();
+
+	spi_write (0xff);	/* soft reset */
+
+	enc_disable ();
+	spi_unlock ();
+
+	/* sleep 1 ms. See errata pt. 2 */
+	udelay (1000);
+}
+
+static void encInit (unsigned char *pEthAddr)
+{
+	unsigned short phid1 = 0;
+	unsigned short phid2 = 0;
+
+	/* switch to bank 0 */
+	m_nic_bfc (CTL_REG_ECON1, (ENC_ECON1_BSEL1 | ENC_ECON1_BSEL0));
+
+	/*
+	 * Setup the buffer space. The reset values are valid for the
+	 * other pointers.
+	 */
+	/* We shall not write to ERXST, see errata pt. 5. Instead we
+	   have to make sure that ENC_RX_BUS_START is 0. */
+	m_nic_write_retry (CTL_REG_ERXSTL, (ENC_RX_BUF_START & 0xFF), 1);
+	m_nic_write_retry (CTL_REG_ERXSTH, (ENC_RX_BUF_START >> 8), 1);
+
+	/* taken from the Linux driver */
+	m_nic_write_retry (CTL_REG_ERXNDL, (ENC_RX_BUF_END & 0xFF), 1);
+	m_nic_write_retry (CTL_REG_ERXNDH, (ENC_RX_BUF_END >> 8), 1);
+
+	m_nic_write_retry (CTL_REG_ERDPTL, (ENC_RX_BUF_START & 0xFF), 1);
+	m_nic_write_retry (CTL_REG_ERDPTH, (ENC_RX_BUF_START >> 8), 1);
+
+	next_pointer_lsb = (ENC_RX_BUF_START & 0xFF);
+	next_pointer_msb = (ENC_RX_BUF_START >> 8);
+
+	/* verify identification */
+	phid1 = phyRead (PHY_REG_PHID1);
+	phid2 = phyRead (PHY_REG_PHID2);
+
+	if (phid1 != ENC_PHID1_VALUE
+	    || (phid2 & ENC_PHID2_MASK) != ENC_PHID2_VALUE) {
+		printf ("ERROR: failed to identify controller\n");
+		printf ("phid1 = %x, phid2 = %x\n",
+			phid1, (phid2 & ENC_PHID2_MASK));
+		printf ("should be phid1 = %x, phid2 = %x\n",
+			ENC_PHID1_VALUE, ENC_PHID2_VALUE);
+	}
+
+	/*
+	 * --- MAC Initialization ---
+	 */
+
+	/* Pull MAC out of Reset */
+
+	/* switch to bank 2 */
+	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+	/* enable MAC to receive frames */
+	/* added some bits from the Linux driver */
+	m_nic_write_retry (CTL_REG_MACON1
+		,(ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS)
+		,10);
+
+	/* configure pad, tx-crc and duplex */
+	/* added a bit from the Linux driver */
+	m_nic_write_retry (CTL_REG_MACON3
+		,(ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN | ENC_MACON3_FRMLNEN)
+		,10);
+
+	/* added 4 new lines from the Linux driver */
+	/* Allow infinite deferals if the medium is continously busy */
+	m_nic_write_retry(CTL_REG_MACON4, (1<<6) /*ENC_MACON4_DEFER*/, 10);
+
+	/* Late collisions occur beyond 63 bytes */
+	m_nic_write_retry(CTL_REG_MACLCON2, 63, 10);
+
+	/* Set (low byte) Non-Back-to_Back Inter-Packet Gap. Recommended 0x12 */
+	m_nic_write_retry(CTL_REG_MAIPGL, 0x12, 10);
+
+	/*
+	* Set (high byte) Non-Back-to_Back Inter-Packet Gap. Recommended
+	* 0x0c for half-duplex. Nothing for full-duplex
+	*/
+	m_nic_write_retry(CTL_REG_MAIPGH, 0x0C, 10);
+
+	/* set maximum frame length */
+	m_nic_write_retry (CTL_REG_MAMXFLL, (ENC_MAX_FRM_LEN & 0xff), 10);
+	m_nic_write_retry (CTL_REG_MAMXFLH, (ENC_MAX_FRM_LEN >> 8), 10);
+
+	/*
+	 * Set MAC back-to-back inter-packet gap. Recommended 0x12 for half duplex
+	 * and 0x15 for full duplex.
+	 */
+	m_nic_write_retry (CTL_REG_MABBIPG, 0x12, 10);
+
+	/* set MAC address */
+
+	/* switch to bank 3 */
+	m_nic_bfs (CTL_REG_ECON1, (ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1));
+
+	m_nic_write_retry (CTL_REG_MAADR0, pEthAddr[5], 1);
+	m_nic_write_retry (CTL_REG_MAADR1, pEthAddr[4], 1);
+	m_nic_write_retry (CTL_REG_MAADR2, pEthAddr[3], 1);
+	m_nic_write_retry (CTL_REG_MAADR3, pEthAddr[2], 1);
+	m_nic_write_retry (CTL_REG_MAADR4, pEthAddr[1], 1);
+	m_nic_write_retry (CTL_REG_MAADR5, pEthAddr[0], 1);
+
+	/*
+	* PHY Initialization taken from the Linux driver
+	 */
+
+	/* Prevent automatic loopback of data beeing transmitted by setting
+	   ENC_PHCON2_HDLDIS */
+	phyWrite(PHY_REG_PHCON2, (1<<8));
+
+	/* LEDs configuration
+	 * LEDA: LACFG = 0100 -> display link status
+	 * LEDB: LBCFG = 0111 -> display TX & RX activity
+	 * STRCH = 1 -> LED pulses
+	 */
+	phyWrite(PHY_REG_PHLCON, 0x0472);
+
+	/* Reset PDPXMD-bit => half duplex */
+	phyWrite(PHY_REG_PHCON1, 0);
+
+	/*
+	 * Receive settings
+	 */
+
+#ifdef CONFIG_USE_IRQ
+	/* enable interrupts */
+	m_nic_bfs (CTL_REG_EIE, ENC_EIE_PKTIE);
+	m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXIE);
+	m_nic_bfs (CTL_REG_EIE, ENC_EIE_RXERIE);
+	m_nic_bfs (CTL_REG_EIE, ENC_EIE_TXERIE);
+	m_nic_bfs (CTL_REG_EIE, ENC_EIE_INTIE);
+#endif
+}
+
+/*****************************************************************************
+ *
+ * Description:
+ *    Read PHY registers.
+ *
+ *    NOTE! This function will change to Bank 2.
+ *
+ * Params:
+ *    [in] addr address of the register to read
+ *
+ * Returns:
+ *    The value in the register
+ */
+static unsigned short phyRead (unsigned char addr)
+{
+	unsigned short ret = 0;
+
+	/* move to bank 2 */
+	m_nic_bfc (CTL_REG_ECON1, ENC_ECON1_BSEL0);
+	m_nic_bfs (CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+	/* write address to MIREGADR */
+	m_nic_write (CTL_REG_MIREGADR, addr);
+
+	/* set MICMD.MIIRD */
+	m_nic_write (CTL_REG_MICMD, ENC_MICMD_MIIRD);
+
+	/* taken from the Linux driver */
+	/* move to bank 3 */
+	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+	/* poll MISTAT.BUSY bit until operation is complete */
+	while ((m_nic_read (CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
+		static int cnt = 0;
+
+		if (cnt++ >= 1000) {
+			/* GJ - this seems extremely dangerous! */
+			/* printf("#"); */
+			cnt = 0;
+		}
+	}
+
+	/* taken from the Linux driver */
+	/* move to bank 2 */
+	m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+	/* clear MICMD.MIIRD */
+	m_nic_write (CTL_REG_MICMD, 0);
+
+	ret = (m_nic_read (CTL_REG_MIRDH) << 8);
+	ret |= (m_nic_read (CTL_REG_MIRDL) & 0xFF);
+
+	return ret;
+}
+
+/*****************************************************************************
+ *
+ * Taken from the Linux driver.
+ * Description:
+ * Write PHY registers.
+ *
+ * NOTE! This function will change to Bank 3.
+ *
+ * Params:
+ * [in] addr address of the register to write to
+ * [in] data to be written
+ *
+ * Returns:
+ *    None
+ */
+static void phyWrite(unsigned char addr, unsigned short data)
+{
+	/* move to bank 2 */
+	m_nic_bfc(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+	/* write address to MIREGADR */
+	m_nic_write(CTL_REG_MIREGADR, addr);
+
+	m_nic_write(CTL_REG_MIWRL, data & 0xff);
+	m_nic_write(CTL_REG_MIWRH, data >> 8);
+
+	/* move to bank 3 */
+	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL0);
+	m_nic_bfs(CTL_REG_ECON1, ENC_ECON1_BSEL1);
+
+	/* poll MISTAT.BUSY bit until operation is complete */
+	while((m_nic_read(CTL_REG_MISTAT) & ENC_MISTAT_BUSY) != 0) {
+		static int cnt = 0;
+
+		if(cnt++ >= 1000) {
+			cnt = 0;
+		}
+	}
+}
diff --git a/drivers/net/mpc5xxx_fec.c b/drivers/net/mpc5xxx_fec.c
index c88e596..bc8c922 100644
--- a/drivers/net/mpc5xxx_fec.c
+++ b/drivers/net/mpc5xxx_fec.c
@@ -250,6 +250,13 @@
 	mpc5xxx_fec_init_phy(dev, bis);
 
 	/*
+	 * Call board-specific PHY fixups (if any)
+	 */
+#ifdef CONFIG_RESET_PHY_R
+	reset_phy();
+#endif
+
+	/*
 	 * Initialize RxBD/TxBD rings
 	 */
 	mpc5xxx_fec_rbd_init(fec);
diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index 54a1bfb..ba9c67e 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -654,6 +654,28 @@
 	return length;
 }
 
+static int smc_write_hwaddr(struct eth_device *dev)
+{
+	int i;
+
+	swap_to(ETHERNET);
+	SMC_SELECT_BANK (dev, 1);
+#ifdef USE_32_BIT
+	for (i = 0; i < 6; i += 2) {
+		word address;
+
+		address = dev->enetaddr[i + 1] << 8;
+		address |= dev->enetaddr[i];
+		SMC_outw(dev, address, (ADDR0_REG + i));
+	}
+#else
+	for (i = 0; i < 6; i++)
+		SMC_outb(dev, dev->enetaddr[i], (ADDR0_REG + i));
+#endif
+	swap_to(FLASH);
+	return 0;
+}
+
 /*
  * Open and Initialize the board
  *
@@ -662,8 +684,6 @@
  */
 static int smc_init(struct eth_device *dev, bd_t *bd)
 {
-	int i;
-
 	swap_to(ETHERNET);
 
 	PRINTK2 ("%s: smc_init\n", SMC_DEV_NAME);
@@ -680,20 +700,6 @@
 	/* conservative setting (10Mbps, HalfDuplex, no AutoNeg.) */
 /*	SMC_SELECT_BANK(dev, 0); */
 /*	SMC_outw(dev, 0, RPC_REG); */
-	SMC_SELECT_BANK (dev, 1);
-
-#ifdef USE_32_BIT
-	for (i = 0; i < 6; i += 2) {
-		word address;
-
-		address = dev->enetaddr[i + 1] << 8;
-		address |= dev->enetaddr[i];
-		SMC_outw(dev, address, (ADDR0_REG + i));
-	}
-#else
-	for (i = 0; i < 6; i++)
-		SMC_outb(dev, dev->enetaddr[i], (ADDR0_REG + i));
-#endif
 
 	printf(SMC_DEV_NAME ": MAC %pM\n", dev->enetaddr);
 
@@ -1360,6 +1366,7 @@
 		return 0;
 	}
 
+	memset(dev, 0, sizeof(*dev));
 	priv->dev_num = dev_num;
 	dev->priv = priv;
 	dev->iobase = base_addr;
@@ -1374,6 +1381,7 @@
 	dev->halt = smc_halt;
 	dev->send = smc_send;
 	dev->recv = smc_rcv;
+	dev->write_hwaddr = smc_write_hwaddr;
 	sprintf(dev->name, "%s-%hu", SMC_DEV_NAME, dev_num);
 
 	eth_register(dev);
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 0820daa..76af939 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -26,6 +26,7 @@
 #include <common.h>
 #include <net.h>
 #include <config.h>
+#include <malloc.h>
 #include <asm/io.h>
 
 #undef DEBUG
@@ -63,26 +64,19 @@
 #define XEL_RSR_RECV_IE_MASK		0x00000008UL
 
 typedef struct {
-	unsigned int baseaddress;	/* Base address for device (IPIF) */
-	unsigned int nexttxbuffertouse;	/* Next TX buffer to write to */
-	unsigned int nextrxbuffertouse;	/* Next RX buffer to read from */
-	unsigned char deviceid;		/* Unique ID of device - for future */
+	u32 baseaddress;	/* Base address for device (IPIF) */
+	u32 nexttxbuffertouse;	/* Next TX buffer to write to */
+	u32 nextrxbuffertouse;	/* Next RX buffer to read from */
+	uchar deviceid;		/* Unique ID of device - for future */
 } xemaclite;
 
 static xemaclite emaclite;
 
 static u32 etherrxbuff[PKTSIZE_ALIGN/4]; /* Receive buffer */
 
-/* hardcoded MAC address for the Xilinx EMAC Core when env is nowhere*/
-#ifdef CONFIG_ENV_IS_NOWHERE
-static u8 emacaddr[ENET_ADDR_LENGTH] = { 0x00, 0x0a, 0x35, 0x00, 0x22, 0x01 };
-#else
-static u8 emacaddr[ENET_ADDR_LENGTH];
-#endif
-
-void xemaclite_alignedread (u32 * srcptr, void *destptr, unsigned bytecount)
+static void xemaclite_alignedread (u32 *srcptr, void *destptr, u32 bytecount)
 {
-	unsigned int i;
+	u32 i;
 	u32 alignbuffer;
 	u32 *to32ptr;
 	u32 *from32ptr;
@@ -107,9 +101,9 @@
 	}
 }
 
-void xemaclite_alignedwrite (void *srcptr, u32 destptr, unsigned bytecount)
+static void xemaclite_alignedwrite (void *srcptr, u32 destptr, u32 bytecount)
 {
-	unsigned i;
+	u32 i;
 	u32 alignbuffer;
 	u32 *to32ptr = (u32 *) destptr;
 	u32 *from32ptr;
@@ -134,23 +128,16 @@
 	*to32ptr++ = alignbuffer;
 }
 
-void eth_halt (void)
+static void emaclite_halt(struct eth_device *dev)
 {
 	debug ("eth_halt\n");
 }
 
-int eth_init (bd_t * bis)
+static int emaclite_init(struct eth_device *dev, bd_t *bis)
 {
-	uchar enetaddr[6];
-
 	debug ("EmacLite Initialization Started\n");
 	memset (&emaclite, 0, sizeof (xemaclite));
-	emaclite.baseaddress = XILINX_EMACLITE_BASEADDR;
-
-	if (!eth_getenv_enetaddr("ethaddr", enetaddr)) {
-		memcpy(enetaddr, emacaddr, ENET_ADDR_LENGTH);
-		eth_setenv_enetaddr("ethaddr", enetaddr);
-	}
+	emaclite.baseaddress = dev->iobase;
 
 /*
  * TX - TX_PING & TX_PONG initialization
@@ -158,7 +145,7 @@
 	/* Restart PING TX */
 	out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET, 0);
 	/* Copy MAC address */
-	xemaclite_alignedwrite (enetaddr,
+	xemaclite_alignedwrite (dev->enetaddr,
 		emaclite.baseaddress, ENET_ADDR_LENGTH);
 	/* Set the length */
 	out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
@@ -171,7 +158,7 @@
 #ifdef CONFIG_XILINX_EMACLITE_TX_PING_PONG
 	/* The same operation with PONG TX */
 	out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET, 0);
-	xemaclite_alignedwrite (enetaddr, emaclite.baseaddress +
+	xemaclite_alignedwrite (dev->enetaddr, emaclite.baseaddress +
 		XEL_BUFFER_OFFSET, ENET_ADDR_LENGTH);
 	out_be32 (emaclite.baseaddress + XEL_TPLR_OFFSET, ENET_ADDR_LENGTH);
 	out_be32 (emaclite.baseaddress + XEL_TSR_OFFSET + XEL_BUFFER_OFFSET,
@@ -194,7 +181,7 @@
 	return 0;
 }
 
-int xemaclite_txbufferavailable (xemaclite * instanceptr)
+static int xemaclite_txbufferavailable (xemaclite *instanceptr)
 {
 	u32 reg;
 	u32 txpingbusy;
@@ -216,12 +203,12 @@
 	return (!(txpingbusy && txpongbusy));
 }
 
-int eth_send (volatile void *ptr, int len) {
+static int emaclite_send (struct eth_device *dev, volatile void *ptr, int len)
+{
+	u32 reg;
+	u32 baseaddress;
 
-	unsigned int reg;
-	unsigned int baseaddress;
-
-	unsigned maxtry = 1000;
+	u32 maxtry = 1000;
 
 	if (len > ENET_MAX_MTU)
 		len = ENET_MAX_MTU;
@@ -293,11 +280,11 @@
 	return 0;
 }
 
-int eth_rx (void)
+static int emaclite_recv(struct eth_device *dev)
 {
-	unsigned int length;
-	unsigned int reg;
-	unsigned int baseaddress;
+	u32 length;
+	u32 reg;
+	u32 baseaddress;
 
 	baseaddress = emaclite.baseaddress + emaclite.nextrxbuffertouse;
 	reg = in_be32 (baseaddress + XEL_RSR_OFFSET);
@@ -322,7 +309,7 @@
 #endif
 	}
 	/* Get the length of the frame that arrived */
-	switch(((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC)) &
+	switch(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0xC))) &
 			0xFFFF0000 ) >> 16) {
 		case 0x806:
 			length = 42 + 20; /* FIXME size of ARP */
@@ -330,7 +317,7 @@
 			break;
 		case 0x800:
 			length = 14 + 14 +
-			(((in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0x10)) &
+			(((ntohl(in_be32 (baseaddress + XEL_RXBUFF_OFFSET + 0x10))) &
 			0xFFFF0000) >> 16); /* FIXME size of IP packet */
 			debug ("IP Packet\n");
 			break;
@@ -353,3 +340,26 @@
 	return 1;
 
 }
+
+int xilinx_emaclite_initialize (bd_t *bis, int base_addr)
+{
+	struct eth_device *dev;
+
+	dev = malloc(sizeof(*dev));
+	if (dev == NULL)
+		hang();
+
+	memset(dev, 0, sizeof(*dev));
+	sprintf(dev->name, "Xilinx_Emaclite");
+
+	dev->iobase = base_addr;
+	dev->priv = 0;
+	dev->init = emaclite_init;
+	dev->halt = emaclite_halt;
+	dev->send = emaclite_send;
+	dev->recv = emaclite_recv;
+
+	eth_register(dev);
+
+	return 0;
+}
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c
index e10c0f3..48033d7 100644
--- a/drivers/qe/uec.c
+++ b/drivers/qe/uec.c
@@ -1223,8 +1223,10 @@
 		i = 50;
 		do {
 			err = curphy->read_status(uec->mii_info);
+			if (!(((i-- > 0) && !uec->mii_info->link) || err))
+				break;
 			udelay(100000);
-		} while (((i-- > 0) && !uec->mii_info->link) || err);
+		} while (1);
 
 		if (err || i <= 0)
 			printf("warning: %s: timeout on PHY link\n", dev->name);
diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c
index 2d3a896..9be784e 100644
--- a/drivers/qe/uec_phy.c
+++ b/drivers/qe/uec_phy.c
@@ -351,6 +351,15 @@
 static int genmii_config_aneg (struct uec_mii_info *mii_info)
 {
 	if (mii_info->autoneg) {
+		/* Speed up the common case, if link is already up, speed and
+		   duplex match, skip auto neg as it already matches */
+		if (!genmii_read_status(mii_info) && mii_info->link)
+			if (mii_info->duplex == DUPLEX_FULL &&
+			    mii_info->speed == SPEED_100)
+				if (mii_info->advertising &
+				    ADVERTISED_100baseT_Full)
+					return 0;
+
 		config_genmii_advert (mii_info);
 		genmii_restart_aneg (mii_info);
 	} else
@@ -389,7 +398,6 @@
 			status = phy_read(mii_info, PHY_BMSR);
 		}
 		mii_info->link = 1;
-		udelay(500000);	/* another 500 ms (results in faster booting) */
 	} else {
 		if (status & PHY_BMSR_LS)
 			mii_info->link = 1;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index bc6480c..b22ca90 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1276,9 +1276,6 @@
 	debug("%s: status %d\n", __func__, req->status);
 
 	packet_received = 1;
-
-	if (req)
-		dev->rx_req = req;
 }
 
 static int alloc_requests(struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
@@ -1287,16 +1284,18 @@
 	dev->tx_req = usb_ep_alloc_request(dev->in_ep, 0);
 
 	if (!dev->tx_req)
-		goto fail;
+		goto fail1;
 
 	dev->rx_req = usb_ep_alloc_request(dev->out_ep, 0);
 
 	if (!dev->rx_req)
-		goto fail;
+		goto fail2;
 
 	return 0;
 
-fail:
+fail2:
+	usb_ep_free_request(dev->in_ep, dev->tx_req);
+fail1:
 	error("can't alloc requests");
 	return -1;
 }
@@ -1791,8 +1790,6 @@
 	}
 
 	dev->network_started = 0;
-	dev->tx_req = NULL;
-	dev->rx_req = NULL;
 
 	packet_received = 0;
 	packet_sent = 0;
@@ -1813,6 +1810,7 @@
 		usb_gadget_handle_interrupts();
 	}
 
+	packet_received = 0;
 	rx_submit(dev, dev->rx_req, 0);
 	return 0;
 fail:
@@ -1823,15 +1821,13 @@
 			volatile void *packet, int length)
 {
 	int			retval;
-	struct usb_request	*req = NULL;
 	struct eth_dev		*dev = &l_ethdev;
+	struct usb_request	*req = dev->tx_req;
 	unsigned long ts;
 	unsigned long timeout = USB_CONNECT_TIMEOUT;
 
 	debug("%s:...\n", __func__);
 
-	req = dev->tx_req;
-
 	req->buf = (void *)packet;
 	req->context = NULL;
 	req->complete = tx_complete;
@@ -1883,8 +1879,7 @@
 			NetReceive(NetRxPackets[0], dev->rx_req->length);
 			packet_received = 0;
 
-			if (dev->rx_req)
-				rx_submit(dev, dev->rx_req, 0);
+			rx_submit(dev, dev->rx_req, 0);
 		} else
 			error("dev->rx_req invalid");
 	}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 3f76c4e..d246978 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1529,7 +1529,7 @@
 	if (usb_pipebulk(pipe))
 		timeout = BULK_TO;
 	else
-		timeout = 100;
+		timeout = 1000;
 
 	/* wait for it to complete */
 	for (;;) {
diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
index af989aa..f38b279 100644
--- a/drivers/usb/musb/musb_hcd.c
+++ b/drivers/usb/musb/musb_hcd.c
@@ -144,19 +144,28 @@
 	u16 csr;
 
 	if (dir_out) {
-		if (!toggle)
-			writew(MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
-		else {
-			csr = readw(&musbr->txcsr);
+		csr = readw(&musbr->txcsr);
+		if (!toggle) {
+			if (csr & MUSB_TXCSR_MODE)
+				csr = MUSB_TXCSR_CLRDATATOG;
+			else
+				csr = 0;
+			writew(csr, &musbr->txcsr);
+		} else {
 			csr |= MUSB_TXCSR_H_WR_DATATOGGLE;
 			writew(csr, &musbr->txcsr);
 			csr |= (toggle << MUSB_TXCSR_H_DATATOGGLE_SHIFT);
 			writew(csr, &musbr->txcsr);
 		}
 	} else {
-		if (!toggle)
-			writew(MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
-		else {
+		if (!toggle) {
+			csr = readw(&musbr->txcsr);
+			if (csr & MUSB_TXCSR_MODE)
+				csr = MUSB_RXCSR_CLRDATATOG;
+			else
+				csr = 0;
+			writew(csr, &musbr->rxcsr);
+		} else {
 			csr = readw(&musbr->rxcsr);
 			csr |= MUSB_RXCSR_H_WR_DATATOGGLE;
 			writew(csr, &musbr->rxcsr);
diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile
index 5f1f800..c2dd514 100644
--- a/examples/standalone/Makefile
+++ b/examples/standalone/Makefile
@@ -82,6 +82,11 @@
 CPPFLAGS := $(filter-out $(RELFLAGS),$(CPPFLAGS))
 endif
 
+# We don't want gcc reordering functions if possible.  This ensures that an
+# application's entry point will be the first function in the application's
+# source file.
+CFLAGS += $(call cc-option,-fno-toplevel-reorder)
+
 all:	$(obj).depend $(OBJS) $(LIB) $(SREC) $(BIN) $(ELF)
 
 #########################################################################
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 003666e..744e961 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -439,11 +439,19 @@
 {
 	dir_entry *realdent;
 	dir_slot *slotptr = (dir_slot *)retdent;
-	__u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
+	__u8 *buflimit = cluster + ((curclust == 0) ?
+					LINEAR_PREFETCH_SIZE :
+					(mydata->clust_size * SECTOR_SIZE)
+				   );
 	__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
 	int idx = 0;
 
-	while ((__u8 *)slotptr < nextclust) {
+	if (counter > VFAT_MAXSEQ) {
+		debug("Error: VFAT name is too long\n");
+		return -1;
+	}
+
+	while ((__u8 *)slotptr < buflimit) {
 		if (counter == 0)
 			break;
 		if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
@@ -452,10 +460,11 @@
 		counter--;
 	}
 
-	if ((__u8 *)slotptr >= nextclust) {
+	if ((__u8 *)slotptr >= buflimit) {
 		dir_slot *slotptr2;
 
-		slotptr--;
+		if (curclust == 0)
+			return -1;
 		curclust = get_fatent(mydata, curclust);
 		if (CHECK_CLUST(curclust, mydata->fatsize)) {
 			debug("curclust: 0x%x\n", curclust);
@@ -470,14 +479,19 @@
 		}
 
 		slotptr2 = (dir_slot *)get_vfatname_block;
-		while (slotptr2->id > 0x01)
+		while (counter > 0) {
+			if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
+			    & 0xff) != counter)
+				return -1;
 			slotptr2++;
+			counter--;
+		}
 
 		/* Save the real directory entry */
-		realdent = (dir_entry *)slotptr2 + 1;
-		while ((__u8 *)slotptr2 >= get_vfatname_block) {
-			slot2str(slotptr2, l_name, &idx);
+		realdent = (dir_entry *)slotptr2;
+		while ((__u8 *)slotptr2 > get_vfatname_block) {
 			slotptr2--;
+			slot2str(slotptr2, l_name, &idx);
 		}
 	} else {
 		/* Save the real directory entry */
@@ -549,7 +563,7 @@
 		dentptr = (dir_entry *)get_dentfromdir_block;
 
 		for (i = 0; i < DIRENTSPERCLUST; i++) {
-			char s_name[14], l_name[256];
+			char s_name[14], l_name[VFAT_MAXLEN_BYTES];
 
 			l_name[0] = '\0';
 			if (dentptr->name[0] == DELETED_FLAG) {
@@ -841,7 +855,11 @@
 		debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%d\n",
 			cursect, mydata->clust_size, DIRENTSPERBLOCK);
 
-		if (disk_read(cursect, mydata->clust_size, do_fat_read_block) < 0) {
+		if (disk_read(cursect,
+				(mydata->fatsize == 32) ?
+				(mydata->clust_size) :
+				LINEAR_PREFETCH_SIZE,
+				do_fat_read_block) < 0) {
 			debug("Error: reading rootdir block\n");
 			return -1;
 		}
@@ -849,9 +867,13 @@
 		dentptr = (dir_entry *) do_fat_read_block;
 
 		for (i = 0; i < DIRENTSPERBLOCK; i++) {
-			char s_name[14], l_name[256];
+			char s_name[14], l_name[VFAT_MAXLEN_BYTES];
 
 			l_name[0] = '\0';
+			if (dentptr->name[0] == DELETED_FLAG) {
+				dentptr++;
+				continue;
+			}
 			if ((dentptr->attr & ATTR_VOLUME)) {
 #ifdef CONFIG_SUPPORT_VFAT
 				if ((dentptr->attr & ATTR_VFAT) &&
@@ -859,7 +881,10 @@
 					prevcksum =
 						((dir_slot *)dentptr)->alias_checksum;
 
-					get_vfatname(mydata, 0,
+					get_vfatname(mydata,
+						     (mydata->fatsize == 32) ?
+						     root_cluster :
+						     0,
 						     do_fat_read_block,
 						     dentptr, l_name);
 
diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h
index 746bf18..cdc5ff1 100644
--- a/include/config_cmd_all.h
+++ b/include/config_cmd_all.h
@@ -70,6 +70,7 @@
 #define CONFIG_CMD_PORTIO	/* Port I/O			*/
 #define CONFIG_CMD_REGINFO	/* Register dump		*/
 #define CONFIG_CMD_REISER	/* Reiserfs support		*/
+#define CONFIG_CMD_RARP		/* rarpboot support		*/
 #define CONFIG_CMD_RUN		/* run command in env variable	*/
 #define CONFIG_CMD_SAVEENV	/* saveenv			*/
 #define CONFIG_CMD_SAVES	/* save S record dump		*/
diff --git a/include/configs/SMN42.h b/include/configs/SMN42.h
index adb6ac5..ba3ada1 100644
--- a/include/configs/SMN42.h
+++ b/include/configs/SMN42.h
@@ -198,6 +198,6 @@
 #define CONFIG_INITRD_TAG
 #define CONFIG_MMC			1
 /* we use this ethernet chip */
-#define CONFIG_ENC28J60
+#define CONFIG_ENC28J60_LPC2292
 
 #endif	/* __CONFIG_H */
diff --git a/include/configs/a4m072.h b/include/configs/a4m072.h
new file mode 100644
index 0000000..a54ab1d
--- /dev/null
+++ b/include/configs/a4m072.h
@@ -0,0 +1,387 @@
+/*
+ * (C) Copyright 2003-2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2010
+ * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC5xxx		1	/* This is an MPC5xxx CPU */
+#define CONFIG_MPC5200		1	/* (more precisely a MPC5200 CPU) */
+#define CONFIG_A4M072		1	/* ... on A4M072 board */
+#define CONFIG_MPC5200_DDR	1	/* ... use DDR RAM */
+
+#define CONFIG_MISC_INIT_R
+
+#define CONFIG_SYS_MPC5XXX_CLKIN	33000000 /* ... running at 33.000000MHz */
+
+#define BOOTFLAG_COLD		0x01	/* Normal Power-On: Boot from FLASH  */
+#define BOOTFLAG_WARM		0x02	/* Software reboot	     */
+
+#define CONFIG_HIGH_BATS	1	/* High BATs supported */
+
+/*
+ * Serial console configuration
+ */
+#define CONFIG_PSC_CONSOLE	1	/* console is on PSC1 */
+#define CONFIG_BAUDRATE		9600	/* ... at 9600 bps */
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200, 230400 }
+/* define to enable silent console */
+#define CONFIG_SILENT_CONSOLE
+#define CONFIG_SYS_DEVICE_NULLDEV	1	/* include nulldev device */
+
+/*
+ * PCI Mapping:
+ * 0x40000000 - 0x4fffffff - PCI Memory
+ * 0x50000000 - 0x50ffffff - PCI IO Space
+ */
+#define CONFIG_PCI
+
+#if defined(CONFIG_PCI)
+#define CONFIG_PCI_PNP		1
+#define CONFIG_PCI_SCAN_SHOW	1
+#define CONFIG_PCIAUTO_SKIP_HOST_BRIDGE	1
+
+#define CONFIG_PCI_MEM_BUS	0x40000000
+#define CONFIG_PCI_MEM_PHYS	CONFIG_PCI_MEM_BUS
+#define CONFIG_PCI_MEM_SIZE	0x10000000
+
+#define CONFIG_PCI_IO_BUS	0x50000000
+#define CONFIG_PCI_IO_PHYS	CONFIG_PCI_IO_BUS
+#define CONFIG_PCI_IO_SIZE	0x01000000
+#endif
+
+#define CONFIG_SYS_XLB_PIPELINING	1
+
+#undef CONFIG_NET_MULTI
+#undef CONFIG_EEPRO100 
+
+/* Partitions */
+#define CONFIG_MAC_PARTITION
+#define CONFIG_DOS_PARTITION
+
+/* USB */
+#define CONFIG_USB_OHCI_NEW
+#define CONFIG_USB_STORAGE
+#define CONFIG_SYS_OHCI_BE_CONTROLLER
+#undef CONFIG_SYS_USB_OHCI_BOARD_INIT
+#define CONFIG_SYS_USB_OHCI_CPU_INIT	1
+#define CONFIG_SYS_USB_OHCI_REGS_BASE	MPC5XXX_USB
+#define CONFIG_SYS_USB_OHCI_SLOT_NAME	"mpc5200"
+#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS	15
+
+#define	CONFIG_TIMESTAMP		/* Print image info with timestamp */
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_EEPROM
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_IDE
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_SNTP
+#define CONFIG_CMD_USB
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DISPLAY
+
+#if defined(CONFIG_PCI)
+#define CONFIG_CMD_PCI
+#endif
+
+#if (TEXT_BASE == 0xFE000000)		/* Boot low with 32 MB Flash */
+#define CONFIG_SYS_LOWBOOT		1
+#define CONFIG_SYS_LOWBOOT32		1
+#endif
+
+/*
+ * Autobooting
+ */
+#define CONFIG_BOOTDELAY	2	/* autoboot after 2 seconds */
+
+#define CONFIG_SYS_AUTOLOAD	"n"
+
+#define CONFIG_AUTOBOOT_KEYED
+#define CONFIG_AUTOBOOT_PROMPT		"autoboot in %d seconds\n", bootdelay
+#define CONFIG_AUTOBOOT_DELAY_STR	"asdfg"
+
+#undef	CONFIG_BOOTARGS
+#define CONFIG_PREBOOT				"run try_update"
+
+#define	CONFIG_EXTRA_ENV_SETTINGS					\
+	"bk=run add_mtd ; run add_consolespec ; bootm 200000\0"	\
+	"cf1=diskboot 200000 0:1\0"	\
+	"bootcmd_cf1=run bcf1\0"	\
+	"bcf=setenv bootargs root=/dev/hda3\0"	\
+	"bootcmd_nfs=run bnfs\0"	\
+	"norargs=setenv bootargs root=/dev/mtdblock3 rootfstype=cramfs\0"	\
+	"bootcmd_nor=cp.b ${kernel_addr} 200000 100000; run norargs addip; run bk\0"	\
+	"bnfs=nfs 200000 ${rootpath}/boot/uImage ; run nfsargs addip ; run bk\0"	\
+	"nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath}\0"	\
+	"try_update=usb start;sleep 2;usb start;sleep 1;fatload usb 0 2F0000 PCPUUPDT 2FF;usb stop;source 2F0000\0"	\
+	"env_addr=FE060000\0"	\
+	"kernel_addr=FE100000\0"	\
+	"rootfs_addr=FE200000\0"	\
+	"add_mtd=setenv bootargs ${bootargs} mtdparts=phys_mapped_flash:384k(u),640k(e),1m(k),30m(r)\0"	\
+	"bcf1=run cf1; run bcf; run addip; run bk\0"	\
+	"add_consolespec=setenv bootargs ${bootargs} console=/dev/null quiet\0"	\
+	"addip=if test \"${ethaddr}\" != \"00:00:00:00:00:00\" ; then if test -n ${ipaddr}; then setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1; fi ; fi\0"	\
+	"hostname=CPUP0\0"	\
+	"ethaddr=00:00:00:00:00:00\0"	\
+	"netdev=eth0\0"	\
+	"bootcmd=run bootcmd_nor\0" \
+	""
+/*
+ * IPB Bus clocking configuration.
+ */
+#undef CONFIG_SYS_IPBCLK_EQUALS_XLBCLK		/* define for 133MHz speed */
+
+/*
+ * I2C configuration
+ */
+#define CONFIG_HARD_I2C			1	/* I2C with hardware support */
+#define CONFIG_SYS_I2C_MODULE		2	/* Select I2C module #1 or #2 */
+
+#define CONFIG_SYS_I2C_SPEED		100000 /* 100 kHz */
+#define CONFIG_SYS_I2C_SLAVE		0x7F
+
+/*
+ * EEPROM configuration
+ */
+#define CONFIG_SYS_I2C_EEPROM_ADDR		0x52	/* 1010010x */
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN		2
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS	6
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS	10
+#define CONFIG_SYS_EEPROM_WREN			1
+#define CONFIG_SYS_EEPROM_WP			GPIO_PSC2_4
+
+/*
+ * Flash configuration
+ */
+#define CONFIG_SYS_FLASH_BASE		0xFE000000
+#define CONFIG_SYS_FLASH_SIZE		0x02000000
+#if !defined(CONFIG_SYS_LOWBOOT)
+#error "CONFIG_SYS_LOWBOOT not defined?"
+#else	/* CONFIG_SYS_LOWBOOT */
+#if defined(CONFIG_SYS_LOWBOOT32)
+#define CONFIG_ENV_ADDR		(CONFIG_SYS_FLASH_BASE + 0x00060000)
+#endif
+#endif	/* CONFIG_SYS_LOWBOOT */
+
+#define CONFIG_SYS_MAX_FLASH_BANKS	1	/* max num of memory banks      */
+#define CONFIG_SYS_MAX_FLASH_SECT	256	/* max num of sects on one chip */
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_CFI_WIDTH	FLASH_CFI_16BIT
+#define CONFIG_SYS_FLASH_BANKS_LIST	{CONFIG_SYS_CS0_START}
+
+/*
+ * Environment settings
+ */
+#define CONFIG_ENV_IS_IN_FLASH	1
+#define CONFIG_ENV_SIZE		0x10000
+#define CONFIG_ENV_SECT_SIZE	0x20000
+#define CONFIG_ENV_ADDR_REDUND	(CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE)
+#define CONFIG_ENV_SIZE_REDUND	CONFIG_ENV_SIZE
+
+#define CONFIG_ENV_OVERWRITE	1
+
+/*
+ * Memory map
+ */
+#define CONFIG_SYS_MBAR		0xF0000000
+#define CONFIG_SYS_SDRAM_BASE	0x00000000
+#define CONFIG_SYS_DEFAULT_MBAR	0x80000000
+
+/* Use SRAM until RAM will be available */
+#define CONFIG_SYS_INIT_RAM_ADDR	MPC5XXX_SRAM
+#define CONFIG_SYS_INIT_RAM_END		MPC5XXX_SRAM_SIZE	/* End of used area in DPRAM */
+
+
+#define CONFIG_SYS_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
+#define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_INIT_RAM_END - CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_GBL_DATA_OFFSET
+
+#define CONFIG_SYS_MONITOR_BASE    TEXT_BASE
+#if (CONFIG_SYS_MONITOR_BASE < CONFIG_SYS_FLASH_BASE)
+#   define CONFIG_SYS_RAMBOOT		1
+#endif
+
+#define CONFIG_SYS_MONITOR_LEN		(384 << 10)	/* Reserve 384 kB for Monitor	*/
+#define CONFIG_SYS_MALLOC_LEN		(128 << 10)	/* Reserve 128 kB for malloc()	*/
+#define CONFIG_SYS_BOOTMAPSZ		(8 << 20)	/* Initial Memory map for Linux */
+
+/*
+ * Ethernet configuration
+ */
+#define CONFIG_MPC5xxx_FEC	1
+#define CONFIG_MPC5xxx_FEC_MII100
+/*
+ * Define CONFIG_MPC5xxx_FEC_MII10 to force FEC at 10Mb
+ */
+/* #define CONFIG_MPC5xxx_FEC_MII10 */
+#define CONFIG_PHY_ADDR		0x1f
+#define CONFIG_PHY_TYPE		0x79c874		/* AMD Phy Controller */
+
+/*
+ * GPIO configuration
+ */
+#define CONFIG_SYS_GPS_PORT_CONFIG	0x18000004
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_CMDLINE_EDITING	1
+#ifdef CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+#endif
+#define CONFIG_SYS_LONGHELP			/* undef to save memory	    */
+#define CONFIG_SYS_PROMPT		"=> "	/* Monitor Command Prompt   */
+#if defined(CONFIG_CMD_KGDB)
+#define CONFIG_SYS_CBSIZE		1024	/* Console I/O Buffer Size  */
+#else
+#define CONFIG_SYS_CBSIZE		256	/* Console I/O Buffer Size  */
+#endif
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16)	/* Print Buffer Size */
+#define CONFIG_SYS_MAXARGS		16		/* max number of command args	*/
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE	/* Boot Argument Buffer Size	*/
+
+#define CONFIG_SYS_MEMTEST_START	0x00100000	/* memtest works on */
+#define CONFIG_SYS_MEMTEST_END		0x00f00000	/* 1 ... 15 MB in DRAM	*/
+
+#define CONFIG_SYS_LOAD_ADDR		0x100000	/* default load address */
+
+#define CONFIG_SYS_HZ			1000	/* decrementer freq: 1 ms ticks */
+
+#define CONFIG_SYS_CACHELINE_SIZE	32	/* For MPC5xxx CPUs */
+#if defined(CONFIG_CMD_KGDB)
+#  define CONFIG_SYS_CACHELINE_SHIFT	5	/* log base 2 of the above value */
+#endif
+
+
+/*
+ * Various low-level settings
+ */
+#define CONFIG_SYS_HID0_INIT		HID0_ICE | HID0_ICFI
+#define CONFIG_SYS_HID0_FINAL		HID0_ICE
+/* Flash at CSBoot, CS0 */
+#define CONFIG_SYS_BOOTCS_START		CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_BOOTCS_SIZE		CONFIG_SYS_FLASH_SIZE
+#define CONFIG_SYS_BOOTCS_CFG		0x0002DD00
+#define CONFIG_SYS_CS0_START		CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_CS0_SIZE		CONFIG_SYS_FLASH_SIZE
+/* External SRAM at CS1 */
+#define CONFIG_SYS_CS1_START		0x62000000
+#define CONFIG_SYS_CS1_SIZE		0x00400000
+#define CONFIG_SYS_CS1_CFG		0x00009930
+#define CONFIG_SYS_SRAM_BASE		CONFIG_SYS_CS1_START
+#define CONFIG_SYS_SRAM_SIZE		CONFIG_SYS_CS1_SIZE
+/* LED display at CS7 */
+#define CONFIG_SYS_CS7_START		0x6a000000
+#define CONFIG_SYS_CS7_SIZE		(64*1024)
+#define CONFIG_SYS_CS7_CFG		0x0000bf30
+
+#define CONFIG_SYS_CS_BURST		0x00000000
+#define CONFIG_SYS_CS_DEADCYCLE		0x33333003
+
+#define CONFIG_SYS_RESET_ADDRESS	0xff000000
+
+/*-----------------------------------------------------------------------
+ * USB stuff
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_USB_CLOCK	0x0001BBBB
+#define CONFIG_USB_CONFIG	0x00001000 /* 0x4000 for SE mode */
+
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff Supports IDE harddisk
+ *-----------------------------------------------------------------------
+ */
+
+#undef  CONFIG_IDE_8xx_PCCARD		/* Use IDE with PC Card	Adapter	*/
+
+#undef	CONFIG_IDE_8xx_DIRECT		/* Direct IDE    not supported	*/
+#undef	CONFIG_IDE_LED			/* LED   for ide not supported	*/
+
+#define CONFIG_IDE_PREINIT
+
+#define CONFIG_SYS_IDE_MAXBUS		1	/* max. 1 IDE bus		*/
+#define CONFIG_SYS_IDE_MAXDEVICE	1	/* max. 2 drives per IDE bus	*/
+
+#define CONFIG_SYS_ATA_IDE0_OFFSET	0x0000
+
+#define CONFIG_SYS_ATA_BASE_ADDR	MPC5XXX_ATA
+
+/* Offset for data I/O			*/
+#define CONFIG_SYS_ATA_DATA_OFFSET	(0x0060)
+
+/* Offset for normal register accesses	*/
+#define CONFIG_SYS_ATA_REG_OFFSET	(CONFIG_SYS_ATA_DATA_OFFSET)
+
+/* Offset for alternate registers	*/
+#define CONFIG_SYS_ATA_ALT_OFFSET	(0x005C)
+
+/* Interval between registers                                                */
+#define CONFIG_SYS_ATA_STRIDE          4
+
+#define CONFIG_ATAPI                   1
+
+/*-----------------------------------------------------------------------
+ * Open firmware flat tree support
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_OF_LIBFDT	1
+#define CONFIG_OF_BOARD_SETUP	1
+
+#define OF_CPU			"PowerPC,5200@0"
+#define OF_SOC			"soc5200@f0000000"
+#define OF_TBCLK		(bd->bi_busfreq / 4)
+#define OF_STDOUT_PATH		"/soc5200@f0000000/serial@2000"
+
+/* Support for the 7-segment display */
+#define CONFIG_SYS_DISP_CHR_RAM	     CONFIG_SYS_CS7_START
+#define CONFIG_SHOW_ACTIVITY		/* used for display realization */
+
+#define CONFIG_SHOW_BOOT_PROGRESS
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/hmi1001.h b/include/configs/hmi1001.h
index d40b7a9..8b0b773 100644
--- a/include/configs/hmi1001.h
+++ b/include/configs/hmi1001.h
@@ -352,6 +352,7 @@
 /* Display addresses						       */
 /*---------------------------------------------------------------------*/
 
+#define CONFIG_PDSP188x
 #define CONFIG_SYS_DISP_CHR_RAM	(CONFIG_SYS_DISPLAY_BASE + 0x38)
 #define CONFIG_SYS_DISP_CWORD		(CONFIG_SYS_DISPLAY_BASE + 0x30)
 
diff --git a/include/configs/lpc2292sodimm.h b/include/configs/lpc2292sodimm.h
index 7ce8d6d..65276a2 100644
--- a/include/configs/lpc2292sodimm.h
+++ b/include/configs/lpc2292sodimm.h
@@ -156,6 +156,6 @@
 #define CONFIG_INITRD_TAG
 #define CONFIG_MMC 1
 /* we use this ethernet chip */
-#define CONFIG_ENC28J60
+#define CONFIG_ENC28J60_LPC2292
 
 #endif	/* __CONFIG_H */
diff --git a/include/configs/manroland/common.h b/include/configs/manroland/common.h
index 0224608..291b669 100644
--- a/include/configs/manroland/common.h
+++ b/include/configs/manroland/common.h
@@ -55,6 +55,11 @@
 #define CONFIG_CMD_MII
 #define CONFIG_CMD_SNTP
 
+/*
+ * 8-symbol LED display (can be accessed with 'display' command)
+ */
+#define CONFIG_PDSP188x
+
 #define	CONFIG_TIMESTAMP	1	/* Print image info with timestamp */
 
 /*
diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h
index 9b1569a..c30cc4c 100644
--- a/include/configs/microblaze-generic.h
+++ b/include/configs/microblaze-generic.h
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2007-2008 Michal Simek
+ * (C) Copyright 2007-2010 Michal Simek
  *
  * Michal SIMEK <monstr@monstr.eu>
  *
@@ -27,31 +27,33 @@
 
 #include "../board/xilinx/microblaze-generic/xparameters.h"
 
-#define	CONFIG_MICROBLAZE	1	/* MicroBlaze CPU */
+/* MicroBlaze CPU */
+#define	CONFIG_MICROBLAZE	1
 #define	MICROBLAZE_V5		1
 
 /* uart */
 #ifdef XILINX_UARTLITE_BASEADDR
-	#define	CONFIG_XILINX_UARTLITE
-	#define	CONFIG_SERIAL_BASE	XILINX_UARTLITE_BASEADDR
-	#define	CONFIG_BAUDRATE		XILINX_UARTLITE_BAUDRATE
-	#define	CONFIG_SYS_BAUDRATE_TABLE	{ CONFIG_BAUDRATE }
-	#define CONSOLE_ARG	"console=console=ttyUL0,115200\0"
+# define CONFIG_XILINX_UARTLITE
+# define CONFIG_SERIAL_BASE	XILINX_UARTLITE_BASEADDR
+# define CONFIG_BAUDRATE	XILINX_UARTLITE_BAUDRATE
+# define CONFIG_SYS_BAUDRATE_TABLE	{ CONFIG_BAUDRATE }
+# define CONSOLE_ARG	"console=console=ttyUL0,115200\0"
 #elif XILINX_UART16550_BASEADDR
-	#define CONFIG_SYS_NS16550	1
-	#define CONFIG_SYS_NS16550_SERIAL
-	#define CONFIG_SYS_NS16550_REG_SIZE	-4
-	#define CONFIG_CONS_INDEX	1
-	#define CONFIG_SYS_NS16550_COM1	(XILINX_UART16550_BASEADDR + 0x1000 + 0x3)
-	#define CONFIG_SYS_NS16550_CLK	XILINX_UART16550_CLOCK_HZ
-	#define	CONFIG_BAUDRATE		115200
+# define CONFIG_SYS_NS16550		1
+# define CONFIG_SYS_NS16550_SERIAL
+# define CONFIG_SYS_NS16550_REG_SIZE	-4
+# define CONFIG_CONS_INDEX		1
+# define CONFIG_SYS_NS16550_COM1 \
+			(XILINX_UART16550_BASEADDR + 0x1000 + 0x3)
+# define CONFIG_SYS_NS16550_CLK	XILINX_UART16550_CLOCK_HZ
+# define CONFIG_BAUDRATE	115200
 
-	/* The following table includes the supported baudrates */
-	#define CONFIG_SYS_BAUDRATE_TABLE  \
-		{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
-	#define CONSOLE_ARG	"console=console=ttyS0,115200\0"
+/* The following table includes the supported baudrates */
+# define CONFIG_SYS_BAUDRATE_TABLE \
+	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}
+# define CONSOLE_ARG	"console=console=ttyS0,115200\0"
 #else
-	#error Undefined uart
+# error Undefined uart
 #endif
 
 /* setting reset address */
@@ -59,41 +61,41 @@
 
 /* ethernet */
 #ifdef XILINX_EMACLITE_BASEADDR
-	#define CONFIG_XILINX_EMACLITE	1
-	#define CONFIG_SYS_ENET
+# define CONFIG_XILINX_EMACLITE		1
+# define CONFIG_SYS_ENET
 #elif XILINX_LLTEMAC_BASEADDR
-	#define CONFIG_XILINX_LL_TEMAC	1
-	#define CONFIG_SYS_ENET
+# define CONFIG_XILINX_LL_TEMAC		1
+# define CONFIG_SYS_ENET
 #endif
 
 #undef ET_DEBUG
 
 /* gpio */
 #ifdef XILINX_GPIO_BASEADDR
-	#define	CONFIG_SYS_GPIO_0		1
-	#define	CONFIG_SYS_GPIO_0_ADDR		XILINX_GPIO_BASEADDR
+# define CONFIG_SYS_GPIO_0		1
+# define CONFIG_SYS_GPIO_0_ADDR		XILINX_GPIO_BASEADDR
 #endif
 
 /* interrupt controller */
 #ifdef XILINX_INTC_BASEADDR
-	#define	CONFIG_SYS_INTC_0		1
-	#define	CONFIG_SYS_INTC_0_ADDR		XILINX_INTC_BASEADDR
-	#define	CONFIG_SYS_INTC_0_NUM		XILINX_INTC_NUM_INTR_INPUTS
+# define CONFIG_SYS_INTC_0		1
+# define CONFIG_SYS_INTC_0_ADDR		XILINX_INTC_BASEADDR
+# define CONFIG_SYS_INTC_0_NUM		XILINX_INTC_NUM_INTR_INPUTS
 #endif
 
 /* timer */
 #ifdef XILINX_TIMER_BASEADDR
-	#if (XILINX_TIMER_IRQ != -1)
-		#define	CONFIG_SYS_TIMER_0		1
-		#define	CONFIG_SYS_TIMER_0_ADDR	XILINX_TIMER_BASEADDR
-		#define	CONFIG_SYS_TIMER_0_IRQ		XILINX_TIMER_IRQ
-		#define	FREQUENCE		XILINX_CLOCK_FREQ
-		#define	CONFIG_SYS_TIMER_0_PRELOAD	( FREQUENCE/1000 )
-	#endif
+# if (XILINX_TIMER_IRQ != -1)
+#  define CONFIG_SYS_TIMER_0		1
+#  define CONFIG_SYS_TIMER_0_ADDR	XILINX_TIMER_BASEADDR
+#  define CONFIG_SYS_TIMER_0_IRQ	XILINX_TIMER_IRQ
+#  define FREQUENCE	XILINX_CLOCK_FREQ
+#  define CONFIG_SYS_TIMER_0_PRELOAD	( FREQUENCE/1000 )
+# endif
 #elif XILINX_CLOCK_FREQ
-	#define	CONFIG_XILINX_CLOCK_FREQ	XILINX_CLOCK_FREQ
+# define CONFIG_XILINX_CLOCK_FREQ	XILINX_CLOCK_FREQ
 #else
-	#error BAD CLOCK FREQ
+# error BAD CLOCK FREQ
 #endif
 /* FSL */
 /* #define	CONFIG_SYS_FSL_2 */
@@ -135,15 +137,20 @@
 /* global pointer */
 #define	CONFIG_SYS_GBL_DATA_SIZE	128 /* size of global data */
 /* start of global data */
-#define	CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE - CONFIG_SYS_GBL_DATA_SIZE)
+#define	CONFIG_SYS_GBL_DATA_OFFSET \
+	(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE \
+				- CONFIG_SYS_GBL_DATA_SIZE)
 
 /* monitor code */
-#define	SIZE			0x40000
+#define	SIZE				0x40000
 #define	CONFIG_SYS_MONITOR_LEN		(SIZE - CONFIG_SYS_GBL_DATA_SIZE)
-#define	CONFIG_SYS_MONITOR_BASE	(CONFIG_SYS_GBL_DATA_OFFSET - CONFIG_SYS_MONITOR_LEN)
-#define	CONFIG_SYS_MONITOR_END		(CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)
+#define	CONFIG_SYS_MONITOR_BASE	\
+			(CONFIG_SYS_GBL_DATA_OFFSET - CONFIG_SYS_MONITOR_LEN)
+#define	CONFIG_SYS_MONITOR_END \
+			(CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)
 #define	CONFIG_SYS_MALLOC_LEN		SIZE
-#define	CONFIG_SYS_MALLOC_BASE		(CONFIG_SYS_MONITOR_BASE - CONFIG_SYS_MALLOC_LEN)
+#define	CONFIG_SYS_MALLOC_BASE \
+			(CONFIG_SYS_MONITOR_BASE - CONFIG_SYS_MALLOC_LEN)
 
 /* stack */
 #define	CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_MALLOC_BASE
@@ -152,55 +159,62 @@
 #define	FLASH
 
 #ifdef FLASH
-	#define	CONFIG_SYS_FLASH_BASE		XILINX_FLASH_START
-	#define	CONFIG_SYS_FLASH_SIZE		XILINX_FLASH_SIZE
-	#define	CONFIG_SYS_FLASH_CFI		1
-	#define	CONFIG_FLASH_CFI_DRIVER	1
-	#define	CONFIG_SYS_FLASH_EMPTY_INFO	1	/* ?empty sector */
-	#define	CONFIG_SYS_MAX_FLASH_BANKS	1	/* max number of memory banks */
-	#define	CONFIG_SYS_MAX_FLASH_SECT	512	/* max number of sectors on one chip */
-	#define	CONFIG_SYS_FLASH_PROTECTION		/* hardware flash protection */
+# define CONFIG_SYS_FLASH_BASE		XILINX_FLASH_START
+# define CONFIG_SYS_FLASH_SIZE		XILINX_FLASH_SIZE
+# define CONFIG_SYS_FLASH_CFI		1
+# define CONFIG_FLASH_CFI_DRIVER	1
+/* ?empty sector */
+# define CONFIG_SYS_FLASH_EMPTY_INFO	1
+/* max number of memory banks */
+# define CONFIG_SYS_MAX_FLASH_BANKS	1
+/* max number of sectors on one chip */
+# define CONFIG_SYS_MAX_FLASH_SECT	512
+/* hardware flash protection */
+# define CONFIG_SYS_FLASH_PROTECTION
 
-	#ifdef	RAMENV
-		#define	CONFIG_ENV_IS_NOWHERE	1
-		#define	CONFIG_ENV_SIZE		0x1000
-		#define	CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
+# ifdef	RAMENV
+#  define CONFIG_ENV_IS_NOWHERE	1
+#  define CONFIG_ENV_SIZE	0x1000
+#  define CONFIG_ENV_ADDR	(CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
 
-	#else	/* !RAMENV */
-		#define	CONFIG_ENV_IS_IN_FLASH	1
-		#define	CONFIG_ENV_SECT_SIZE	0x20000	/* 128K(one sector) for env */
-		#define	CONFIG_ENV_ADDR		(CONFIG_SYS_FLASH_BASE + (2 * CONFIG_ENV_SECT_SIZE))
-		#define	CONFIG_ENV_SIZE		0x20000
-	#endif /* !RAMBOOT */
+# else	/* !RAMENV */
+#  define CONFIG_ENV_IS_IN_FLASH	1
+/* 128K(one sector) for env */
+#  define CONFIG_ENV_SECT_SIZE	0x20000
+#  define CONFIG_ENV_ADDR \
+			(CONFIG_SYS_FLASH_BASE + (2 * CONFIG_ENV_SECT_SIZE))
+#  define CONFIG_ENV_SIZE	0x20000
+# endif /* !RAMBOOT */
 #else /* !FLASH */
-	/* ENV in RAM */
-	#define	CONFIG_SYS_NO_FLASH		1
-	#define	CONFIG_ENV_IS_NOWHERE	1
-	#define	CONFIG_ENV_SIZE		0x1000
-	#define	CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
-	#define	CONFIG_SYS_FLASH_PROTECTION		/* hardware flash protection */
+/* ENV in RAM */
+# define CONFIG_SYS_NO_FLASH	1
+# define CONFIG_ENV_IS_NOWHERE	1
+# define CONFIG_ENV_SIZE	0x1000
+# define CONFIG_ENV_ADDR	(CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
+/* hardware flash protection */
+# define CONFIG_SYS_FLASH_PROTECTION
 #endif /* !FLASH */
 
 /* system ace */
 #ifdef XILINX_SYSACE_BASEADDR
-	#define	CONFIG_SYSTEMACE
-	/* #define DEBUG_SYSTEMACE */
-	#define	SYSTEMACE_CONFIG_FPGA
-	#define	CONFIG_SYS_SYSTEMACE_BASE	XILINX_SYSACE_BASEADDR
-	#define	CONFIG_SYS_SYSTEMACE_WIDTH	XILINX_SYSACE_MEM_WIDTH
-	#define	CONFIG_DOS_PARTITION
+# define CONFIG_SYSTEMACE
+/* #define DEBUG_SYSTEMACE */
+# define SYSTEMACE_CONFIG_FPGA
+# define CONFIG_SYS_SYSTEMACE_BASE	XILINX_SYSACE_BASEADDR
+# define CONFIG_SYS_SYSTEMACE_WIDTH	XILINX_SYSACE_MEM_WIDTH
+# define CONFIG_DOS_PARTITION
 #endif
 
 #if defined(XILINX_USE_ICACHE)
-	#define CONFIG_ICACHE
+# define CONFIG_ICACHE
 #else
-	#undef CONFIG_ICACHE
+# undef CONFIG_ICACHE
 #endif
 
 #if defined(XILINX_USE_DCACHE)
-	#define CONFIG_DCACHE
+# define CONFIG_DCACHE
 #else
-	#undef CONFIG_DCACHE
+# undef CONFIG_DCACHE
 #endif
 
 /*
@@ -222,36 +236,39 @@
 #define CONFIG_CMD_ECHO
 
 #if defined(CONFIG_DCACHE) || defined(CONFIG_ICACHE)
-	#define CONFIG_CMD_CACHE
+# define CONFIG_CMD_CACHE
 #else
-	#undef CONFIG_CMD_CACHE
+# undef CONFIG_CMD_CACHE
 #endif
 
 #ifndef CONFIG_SYS_ENET
-	#undef CONFIG_CMD_NET
+# undef CONFIG_CMD_NET
+# undef CONFIG_NET_MULTI
 #else
-	#define CONFIG_CMD_PING
+# define CONFIG_CMD_PING
+# define CONFIG_CMD_DHCP
+# define CONFIG_NET_MULTI
 #endif
 
 #if defined(CONFIG_SYSTEMACE)
-	#define CONFIG_CMD_EXT2
-	#define CONFIG_CMD_FAT
+# define CONFIG_CMD_EXT2
+# define CONFIG_CMD_FAT
 #endif
 
 #if defined(FLASH)
-	#define CONFIG_CMD_ECHO
-	#define CONFIG_CMD_FLASH
-	#define CONFIG_CMD_IMLS
-	#define CONFIG_CMD_JFFS2
+# define CONFIG_CMD_ECHO
+# define CONFIG_CMD_FLASH
+# define CONFIG_CMD_IMLS
+# define CONFIG_CMD_JFFS2
 
-	#if !defined(RAMENV)
-		#define CONFIG_CMD_SAVEENV
-		#define CONFIG_CMD_SAVES
-	#endif
+# if !defined(RAMENV)
+#  define CONFIG_CMD_SAVEENV
+#  define CONFIG_CMD_SAVES
+# endif
 #else
-	#undef CONFIG_CMD_IMLS
-	#undef CONFIG_CMD_FLASH
-	#undef CONFIG_CMD_JFFS2
+# undef CONFIG_CMD_IMLS
+# undef CONFIG_CMD_FLASH
+# undef CONFIG_CMD_JFFS2
 #endif
 
 #if defined(CONFIG_CMD_JFFS2)
@@ -259,21 +276,26 @@
 #define CONFIG_CMD_MTDPARTS	/* mtdparts command line support */
 #define CONFIG_MTD_DEVICE	/* needed for mtdparts commands */
 #define CONFIG_FLASH_CFI_MTD
-#define MTDIDS_DEFAULT		"nor0=ml401-0"
+#define MTDIDS_DEFAULT		"nor0=flash-0"
 
 /* default mtd partition table */
-#define MTDPARTS_DEFAULT	"mtdparts=ml401-0:256k(u-boot),"\
+#define MTDPARTS_DEFAULT	"mtdparts=flash-0:256k(u-boot),"\
 				"256k(env),3m(kernel),1m(romfs),"\
 				"1m(cramfs),-(jffs2)"
 #endif
 
 /* Miscellaneous configurable options */
 #define	CONFIG_SYS_PROMPT	"U-Boot-mONStR> "
-#define	CONFIG_SYS_CBSIZE	512	/* size of console buffer */
-#define	CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) /* print buffer size */
-#define	CONFIG_SYS_MAXARGS	15	/* max number of command args */
+/* size of console buffer */
+#define	CONFIG_SYS_CBSIZE	512
+ /* print buffer size */
+#define	CONFIG_SYS_PBSIZE \
+		(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+/* max number of command args */
+#define	CONFIG_SYS_MAXARGS	15
 #define	CONFIG_SYS_LONGHELP
-#define	CONFIG_SYS_LOAD_ADDR	XILINX_RAM_START /* default load address */
+/* default load address */
+#define	CONFIG_SYS_LOAD_ADDR	XILINX_RAM_START
 
 #define	CONFIG_BOOTDELAY	-1	/* -1 disables auto-boot */
 #define	CONFIG_BOOTARGS		"root=romfs"
@@ -290,9 +312,9 @@
 
 #define	CONFIG_PREBOOT	"echo U-BOOT for ${hostname};setenv preboot;echo"
 
-#define	CONFIG_EXTRA_ENV_SETTINGS	"unlock=yes\0" /* hardware flash protection */\
-					"nor0=ml401-0\0"\
-					"mtdparts=mtdparts=ml401-0:"\
+#define	CONFIG_EXTRA_ENV_SETTINGS	"unlock=yes\0" \
+					"nor0=flash-0\0"\
+					"mtdparts=mtdparts=flash-0:"\
 					"256k(u-boot),256k(env),3m(kernel),"\
 					"1m(romfs),1m(cramfs),-(jffs2)\0"
 
@@ -301,7 +323,7 @@
 /* Use the HUSH parser */
 #define CONFIG_SYS_HUSH_PARSER
 #ifdef CONFIG_SYS_HUSH_PARSER
-#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+# define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
 #endif
 
 #endif	/* __CONFIG_H */
diff --git a/include/fat.h b/include/fat.h
index de48afd..afb2116 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -30,6 +30,10 @@
 #include <asm/byteorder.h>
 
 #define CONFIG_SUPPORT_VFAT
+/* Maximum Long File Name length supported here is 128 UTF-16 code units */
+#define VFAT_MAXLEN_BYTES	256 /* Maximum LFN buffer in bytes */
+#define VFAT_MAXSEQ		9   /* Up to 9 of 13 2-byte UTF-16 entries */
+#define LINEAR_PREFETCH_SIZE	(SECTOR_SIZE*2) /* Prefetch buffer size */
 
 #define SECTOR_SIZE FS_BLOCK_SIZE
 
diff --git a/include/fdt_support.h b/include/fdt_support.h
index fd94929..deb5dda 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -87,6 +87,7 @@
 int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
 					phys_addr_t compat_off);
 int fdt_alloc_phandle(void *blob);
+int fdt_add_edid(void *blob, const char *compat, unsigned char *buf);
 
 #endif /* ifdef CONFIG_OF_LIBFDT */
 #endif /* ifndef __FDT_SUPPORT_H */
diff --git a/include/led-display.h b/include/led-display.h
new file mode 100644
index 0000000..41c3744
--- /dev/null
+++ b/include/led-display.h
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2005-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2010
+ * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _led_display_h_
+#define _led_display_h_
+
+/* Display Commands */
+#define DISPLAY_CLEAR	0x1 /* Clear the display */
+#define DISPLAY_HOME	0x2 /* Set cursor at home position */
+#define DISPLAY_MARK	0x4 /* Enable the decimal point led, if implemented */
+
+void display_set(int cmd);
+int display_putc(char c);
+#endif
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 16556c4..3b18d7d 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -208,10 +208,6 @@
 	int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 	int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
 
-	/* Power Management functions */
-	int (*suspend) (struct mtd_info *mtd);
-	void (*resume) (struct mtd_info *mtd);
-
 	/* Bad block management functions */
 	int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
 	int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
@@ -259,7 +255,9 @@
 extern struct mtd_info *get_mtd_device_nm(const char *name);
 
 extern void put_mtd_device(struct mtd_info *mtd);
-
+extern void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
+				 const uint64_t length, uint64_t *len_incl_bad,
+				 int *truncated);
 /* XXX U-BOOT XXX */
 #if 0
 struct mtd_notifier {
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 68e174e..5465562 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -154,6 +154,7 @@
 /*
  * OneNAND Flash Manufacturer ID Codes
  */
+#define ONENAND_MFR_NUMONYX	0x20
 #define ONENAND_MFR_SAMSUNG	0xec
 
 /**
diff --git a/include/mpc5xxx.h b/include/mpc5xxx.h
index 2d343c7..859d696 100644
--- a/include/mpc5xxx.h
+++ b/include/mpc5xxx.h
@@ -160,11 +160,12 @@
 #define MPC5XXX_WU_GPIO_DATA_O  (MPC5XXX_WU_GPIO + 0x000c)
 #define MPC5XXX_WU_GPIO_DATA_I  (MPC5XXX_WU_GPIO + 0x0020)
 
-/* GPIO pins */
+/* GPIO pins, for Rev.B chip */
 #define GPIO_WKUP_7		0x80000000UL
 #define GPIO_PSC6_0		0x10000000UL
 #define GPIO_PSC3_9		0x04000000UL
 #define GPIO_PSC1_4		0x01000000UL
+#define GPIO_PSC2_4		0x02000000UL
 
 #define MPC5XXX_GPIO_SIMPLE_PSC6_3   0x20000000UL
 #define MPC5XXX_GPIO_SIMPLE_PSC6_2   0x10000000UL
diff --git a/include/nand.h b/include/nand.h
index 8bdf419..a452411 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -98,13 +98,16 @@
 typedef struct nand_read_options nand_read_options_t;
 
 struct nand_erase_options {
-	ulong length;		/* number of bytes to erase */
-	ulong offset;		/* first address in NAND to erase */
+	loff_t length;		/* number of bytes to erase */
+	loff_t offset;		/* first address in NAND to erase */
 	int quiet;		/* don't display progress messages */
 	int jffs2;		/* if true: format for jffs2 usage
 				 * (write appropriate cleanmarker blocks) */
 	int scrub;		/* if true, really clean NAND by erasing
 				 * bad blocks (UNSAFE) */
+
+	/* Don't include skipped bad blocks in size to be erased */
+	int spread;
 };
 
 typedef struct nand_erase_options nand_erase_options_t;
diff --git a/include/netdev.h b/include/netdev.h
index 94eedfe..7f66419 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -54,6 +54,8 @@
 int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr);
 int e1000_initialize(bd_t *bis);
 int eepro100_initialize(bd_t *bis);
+int enc28j60_initialize(unsigned int bus, unsigned int cs,
+	unsigned int max_hz, unsigned int mode);
 int ep93xx_eth_initialize(u8 dev_num, int base_addr);
 int ethoc_initialize(u8 dev_num, int base_addr);
 int eth_3com_initialize (bd_t * bis);
@@ -85,9 +87,9 @@
 int smc911x_initialize(u8 dev_num, int base_addr);
 int smc91111_initialize(u8 dev_num, int base_addr);
 int tsi108_eth_initialize(bd_t *bis);
-int uec_initialize(int index);
 int uec_standard_init(bd_t *bis);
 int uli526x_initialize(bd_t *bis);
+int xilinx_emaclite_initialize (bd_t *bis, int base_addr);
 int sh_eth_initialize(bd_t *bis);
 int dm9000_initialize(bd_t *bis);
 
diff --git a/lib/gunzip.c b/lib/gunzip.c
index d2b7ad4..482a476 100644
--- a/lib/gunzip.c
+++ b/lib/gunzip.c
@@ -96,11 +96,6 @@
 
 	s.zalloc = zalloc;
 	s.zfree = zfree;
-#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
-	s.outcb = (cb_func)WATCHDOG_RESET;
-#else
-	s.outcb = Z_NULL;
-#endif	/* CONFIG_HW_WATCHDOG */
 
 	r = inflateInit2(&s, -MAX_WBITS);
 	if (r != Z_OK) {
diff --git a/lib/zlib.c b/lib/zlib.c
index 26e5af1..e19484a 100644
--- a/lib/zlib.c
+++ b/lib/zlib.c
@@ -29,6 +29,7 @@
 #include <common.h>
 #include <compiler.h>
 #include <asm/unaligned.h>
+#include <watchdog.h>
 #include "u-boot/zlib.h"
 #undef	OFF				/* avoid conflicts */
 
@@ -1075,8 +1076,7 @@
     state->hold = 0;
     state->bits = 0;
     state->lencode = state->distcode = state->next = state->codes;
-    if (strm->outcb != Z_NULL)
-	(*strm->outcb)(Z_NULL, 0);
+    WATCHDOG_RESET();
     Tracev((stderr, "inflate: reset\n"));
     return Z_OK;
 }
@@ -1599,6 +1599,7 @@
             strm->adler = state->check = adler32(0L, Z_NULL, 0);
             state->mode = TYPE;
         case TYPE:
+	    WATCHDOG_RESET();
             if (flush == Z_BLOCK) goto inf_leave;
         case TYPEDO:
             if (state->last) {
@@ -1776,8 +1777,7 @@
             Tracev((stderr, "inflate:       codes ok\n"));
             state->mode = LEN;
         case LEN:
-            if (strm->outcb != Z_NULL) /* for watchdog (U-Boot) */
-                (*strm->outcb)(Z_NULL, 0);
+	    WATCHDOG_RESET();
             if (have >= 6 && left >= 258) {
                 RESTORE();
                 inflate_fast(strm, out);
@@ -1990,8 +1990,7 @@
         return Z_STREAM_ERROR;
     state = (struct inflate_state FAR *)strm->state;
     if (state->window != Z_NULL) {
-	if (strm->outcb != Z_NULL)
-		(*strm->outcb)(Z_NULL, 0);
+	WATCHDOG_RESET();
 	ZFREE(strm, state->window);
     }
     ZFREE(strm, strm->state);
diff --git a/net/Makefile b/net/Makefile
index 4f819dd..216d1ec 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -32,7 +32,7 @@
 COBJS-$(CONFIG_CMD_NET)  += eth.o
 COBJS-$(CONFIG_CMD_NET)  += net.o
 COBJS-$(CONFIG_CMD_NFS)  += nfs.o
-COBJS-$(CONFIG_CMD_NET)  += rarp.o
+COBJS-$(CONFIG_CMD_RARP) += rarp.o
 COBJS-$(CONFIG_CMD_SNTP) += sntp.o
 COBJS-$(CONFIG_CMD_NET)  += tftp.o
 
diff --git a/net/eth.c b/net/eth.c
index 993306f..5c70d4f 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -263,7 +263,6 @@
 			dev = dev->next;
 		} while(dev != eth_devices);
 
-#ifdef CONFIG_NET_MULTI
 		/* update current ethernet name */
 		if (eth_current) {
 			char *act = getenv("ethact");
@@ -271,7 +270,6 @@
 				setenv("ethact", eth_current->name);
 		} else
 			setenv("ethact", NULL);
-#endif
 
 		putc ('\n');
 	}
@@ -441,7 +439,7 @@
 void eth_try_another(int first_restart)
 {
 	static struct eth_device *first_failed = NULL;
-	char *ethrotate;
+	char *ethrotate, *act;
 
 	/*
 	 * Do not rotate between network interfaces when
@@ -460,21 +458,16 @@
 
 	eth_current = eth_current->next;
 
-#ifdef CONFIG_NET_MULTI
 	/* update current ethernet name */
-	{
-		char *act = getenv("ethact");
-		if (act == NULL || strcmp(act, eth_current->name) != 0)
-			setenv("ethact", eth_current->name);
-	}
-#endif
+	act = getenv("ethact");
+	if (act == NULL || strcmp(act, eth_current->name) != 0)
+		setenv("ethact", eth_current->name);
 
 	if (first_failed == eth_current) {
 		NetRestartWrap = 1;
 	}
 }
 
-#ifdef CONFIG_NET_MULTI
 void eth_set_current(void)
 {
 	static char *act = NULL;
@@ -501,7 +494,6 @@
 
 	setenv("ethact", eth_current->name);
 }
-#endif
 
 char *eth_get_name (void)
 {
diff --git a/net/net.c b/net/net.c
index 33fcd90..d5a5429 100644
--- a/net/net.c
+++ b/net/net.c
@@ -80,7 +80,9 @@
 #include <net.h>
 #include "bootp.h"
 #include "tftp.h"
+#ifdef CONFIG_CMD_RARP
 #include "rarp.h"
+#endif
 #include "nfs.h"
 #ifdef CONFIG_STATUS_LED
 #include <status_led.h>
@@ -401,11 +403,13 @@
 			BootpRequest ();
 			break;
 
+#if defined(CONFIG_CMD_RARP)
 		case RARP:
 			RarpTry = 0;
 			NetOurIP = 0;
 			RarpRequest ();
 			break;
+#endif
 #if defined(CONFIG_CMD_PING)
 		case PING:
 			PingStart();
@@ -1492,6 +1496,7 @@
 		}
 		break;
 
+#ifdef CONFIG_CMD_RARP
 	case PROT_RARP:
 		debug("Got RARP\n");
 		arp = (ARP_t *)ip;
@@ -1515,7 +1520,7 @@
 			(*packetHandler)(0,0,0,0);
 		}
 		break;
-
+#endif
 	case PROT_IP:
 		debug("Got IP\n");
 		/* Before we start poking the header, make sure it is there */
@@ -1729,10 +1734,12 @@
 		}
 		/* Fall through */
 
-	case DHCP:
+#ifdef CONFIG_CMD_RARP
 	case RARP:
+#endif
 	case BOOTP:
 	case CDP:
+	case DHCP:
 		if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
 #ifdef CONFIG_NET_MULTI
 			extern int eth_get_dev_index (void);
diff --git a/tools/imls/Makefile b/tools/imls/Makefile
index 8407277..0caa397 100644
--- a/tools/imls/Makefile
+++ b/tools/imls/Makefile
@@ -67,7 +67,7 @@
 	$(CC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(STRIP) $@
 
-# Some files complain if compiled with -pedantic, use FIT_CFLAGS
+# Some files complain if compiled with -pedantic, use HOSTCFLAGS_NOPED
 $(obj)image.o: $(SRCTREE)/common/image.c
 	$(CC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<