Merge with /home/wd/git/u-boot/custodian/u-boot-ppc4xx
diff --git a/CHANGELOG b/CHANGELOG
index 284ba76..7425ceb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,153 @@
+commit 94abd7c0583ebe01e799b25f451201deeaab550d
+Author: Wolfgang Denk <wd@denx.de>
+Date:	Wed Apr 4 01:49:15 2007 +0200
+
+    Minor cleanup.
+
+commit aea03c4e8c3a21ce43d3faf48a6e6d474c8bdf73
+Author: Gerald Van Baren <vanbaren@cideas.com>
+Date:	Sat Mar 31 14:30:53 2007 -0400
+
+    Fix some minor whitespace violations.
+
+commit 213bf8c822de8eecaf69860684469cdaba2e9e6a
+Author: Gerald Van Baren <vanbaren@cideas.com>
+Date:	Sat Mar 31 12:23:51 2007 -0400
+
+    Add a flattened device tree (fdt) command (2 of 2)
+
+    Modifications to the existing code to support the new fdt command.
+
+commit 781e09ee6e3e3e392ab362c1f0ef1068adc76e3e
+Author: Gerald Van Baren <vanbaren@cideas.com>
+Date:	Sat Mar 31 12:22:10 2007 -0400
+
+    Add a flattened device tree (fdt) command (1 of 2)
+
+    The fdt command uses David Gibson's libfdt library to manipulate as well
+    as print the flattened device tree.  This patch is the new command,
+    the second part is the modifications to the existing code.
+
+commit 3af0d587d93e0be5f96e1b30fa41e662f8b0803e
+Author: Gerald Van Baren <vanbaren@cideas.com>
+Date:	Sat Mar 31 12:13:43 2007 -0400
+
+    libfdt: Enhanced and published fdt_next_tag()
+
+    Enhanced the formerly private function _fdt_next_tag() to allow stepping
+      through the tree, used to produce a human-readable dump, and made
+      it part of the published interface.
+    Also added some comments.
+
+commit fa3a74cec73dfd06a5ae35a9a3368200273aaa71
+Author: Gerald Van Baren <vanbaren@cideas.com>
+Date:	Sat Mar 31 12:05:39 2007 -0400
+
+    libfdt: Customizations for use by u-boot.
+
+    Changes to David Gibson's original source to fit into u-boot's
+    environment.  No functionality changes.
+
+commit 35748177c64a4a83a00057e93bb33e40278a2a96
+Author: Gerald Van Baren <vanbaren@cideas.com>
+Date:	Sat Mar 31 12:00:56 2007 -0400
+
+    libfdt: Import libfdt source (2 of 2)
+
+    This adds the applicable libfdt source files (unmodified) and a README
+    to explain where the source came from.
+
+commit 7cd5da0fe877e7171a4cdd44880bce783132871a
+Author: Gerald Van Baren <vanbaren@cideas.com>
+Date:	Sat Mar 31 11:59:59 2007 -0400
+
+    libfdt: Import libfdt source (1 of 2)
+
+    This adds the applicable libfdt source files (unmodified) and a README
+    to explain where the source came from.
+
+commit 342cd097be1e7affe82f42ab3da220959a699e64
+Author: Michal Simek <monstr@monstr.eu>
+Date:	Fri Mar 30 22:52:09 2007 +0200
+
+    [PATCH] Clean include dependence
+
+commit 6f934210fb293fde2cfb4251c6d96fdc58b6a906
+Author: Michal Simek <monstr@monstr.eu>
+Date:	Fri Mar 30 22:42:45 2007 +0200
+
+    [CLEAN] Remove inefficient Suzaku code
+
+commit 5da048adf44bea5e3b94080d02903c2e3fe7aa4a
+Author: Michal Simek <monstr@monstr.eu>
+Date:	Tue Mar 27 00:32:16 2007 +0200
+
+    PATCH: Resolve GPL license problem
+
+commit 1798049522f594013aea29457d46794298c6ae15
+Author: Michal Simek <root@monstr.eu>
+Date:	Mon Mar 26 01:39:07 2007 +0200
+
+    Support for XUPV2P board
+    Reset support
+    BSP autoconfig support
+
+commit 6eb1df835191d8ce4b81d5af40fa8e0fbe78e997
+Author: Jon Loeliger <jdl@freescale.com>
+Date:	Tue Dec 12 11:02:20 2006 -0600
+
+    Fix 8641HPCN problem with ld version 2.16
+
+    (Dot outside sections problem).
+
+    This fix is in the spirit of 807d5d7319330e336ab34a5623c5e0d73b87d540.
+
+    Signed-off-by: Jon Loeliger <jdl@freescale.com>
+
+commit 9964a4dd0d4ef5a037febaebf1aa494b1a72991c
+Author: Haiying Wang <haiying.wang@freescale.com>
+Date:	Thu Dec 7 10:35:55 2006 -0600
+
+    Set Rev 2.x 86xx PIC in mixed mode.
+
+    Prevent false interrupt from hanging Linux as MSR[EE] is set
+    to enable interrupts by changing the PIC out of the default
+    pass through mode into mixed mode.
+
+    Signed-off-by: Haiying Wang <haiying.wang@freescale.com>
+    Signed-off-by: Jon Loeliger <jdl@freescale.com>
+
+commit 5a58a73ceb0a4059c42ef64cedbc1a45e0aaa00e
+Author: Jason Jin <jason.jin@freescale.com>
+Date:	Thu Dec 7 10:32:35 2006 -0600
+
+    Add flash cmd function to 8641HPCN ramboot
+
+    Also fixes some commmand for 8641 HPCN ramboot case.
+
+    Signed-off-by: Jason Jin <jason.jin@freescale.com>
+    Signed-off-by: Jon Loeliger <jdl@freescale.com>
+
+commit 2ccceacc04b009d923afb7c26189ba2f8a2a5d46
+Author: Ed Swarthout <ed.swarthout@freescale.com>
+Date:	Thu Dec 7 10:34:14 2006 -0600
+
+    Add support for 8641 Rev 2 silicon.
+
+    Without this patch, I am unable to get to the prompt on rev 2 silicon.
+    Only set ddrioovcr for rev1.
+
+    Signed-off-by: Ed Swarthout<ed.swarthout@freescale.com>
+    Signed-off-by: Jon Loeliger <jdl@freescale.com>
+
+commit 44ba464b99001f8bd1c456a1e9d59726252f707a
+Author: Wolfgang Denk <wd@denx.de>
+Date:	Thu Mar 22 00:13:12 2007 +0100
+
+    Code cleanup / re-insert previous Copyright entries.
+
+    Signed-off-by: Wolfgang Denk <wd@denx.de>
+
 commit 2a8dfe08359a1b663418b2faa1da1d7bce34d302
 Author: Wolfgang Denk <wd@denx.de>
 Date:	Wed Mar 21 23:26:15 2007 +0100
@@ -148,6 +298,38 @@
 
     [Blackfin][PATCH] code cleanup
 
+commit cfc67116a706fd18b8f6a9c11a16753c5626d689
+Author: Michal Simek <monstr@monstr.eu>
+Date:	Sun Mar 11 13:48:24 2007 +0100
+
+    [Microblaze][PATCH] part 2
+    timer support
+    interrupt controller support
+    flash support
+    ethernet support
+    cache support
+    board information support
+    env support
+    booting image support
+
+    adding support for Xilinx ML401
+
+commit 76316a318de91f6184e7c22a10e02d275ade2441
+Author: Michal Simek <monstr@monstr.eu>
+Date:	Sun Mar 11 13:42:58 2007 +0100
+
+    [Microblaze][PATCH]
+    timer support
+    interrupt controller support
+    flash support
+    ethernet support
+    cache support
+    board information support
+    env support
+    booting image support
+
+    adding support for Xilinx ML401
+
 commit 8db13d63157811c839d15a313d9f2d2f5fd10af3
 Author: Aubrey Li <aubrey.adi@gmail.com>
 Date:	Sat Mar 10 23:49:29 2007 +0800
diff --git a/CREDITS b/CREDITS
index 0099bd4..7af1b80 100644
--- a/CREDITS
+++ b/CREDITS
@@ -474,3 +474,8 @@
 E: timur@freescale.com
 D: Support for MPC8349E-mITX
 W: www.freescale.com
+
+N: Michal Simek
+E: monstr@monstr.eu
+D: Support for Microblaze, ML401, XUPV2P board
+W: www.monstr.eu
diff --git a/MAINTAINERS b/MAINTAINERS
index 68233cf..2a43848 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -564,6 +564,11 @@
 
 	SUZAKU			MicroBlaze
 
+Michal Simek <monstr@monstr.eu>
+
+	ML401			MicroBlaze
+	XUPV2P			MicroBlaze
+
 #########################################################################
 # Coldfire Systems:							#
 #									#
diff --git a/MAKEALL b/MAKEALL
index a02d8c1..47f2030 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -293,7 +293,7 @@
 #########################################################################
 
 LIST_microblaze="	\
-	suzaku
+	suzaku		ml401		xupv2p
 "
 
 #########################################################################
diff --git a/Makefile b/Makefile
index 546960d..84b49fe 100644
--- a/Makefile
+++ b/Makefile
@@ -2346,6 +2346,16 @@
 	@echo "#define CONFIG_SUZAKU 1" >> $(obj)include/config.h
 	@$(MKCONFIG) -a $(@:_config=) microblaze microblaze suzaku AtmarkTechno
 
+ml401_config:	unconfig
+	@ >include/config.h
+	@echo "#define CONFIG_ML401 1" >> include/config.h
+	@./mkconfig -a $(@:_config=) microblaze microblaze ml401 xilinx
+
+xupv2p_config:	unconfig
+	@ >include/config.h
+	@echo "#define CONFIG_XUPV2P 1" >> include/config.h
+	@./mkconfig -a $(@:_config=) microblaze microblaze xupv2p xilinx
+
 #########################################################################
 ## Blackfin
 #########################################################################
diff --git a/README b/README
index 1542864..87d6d10 100644
--- a/README
+++ b/README
@@ -164,6 +164,7 @@
 - lib_mips	Files generic to MIPS	 architecture
 - lib_nios	Files generic to NIOS	 architecture
 - lib_ppc	Files generic to PowerPC architecture
+- libfdt 	Library files to support flattened device trees
 - net		Networking code
 - post		Power On Self Test
 - rtc		Real Time Clock drivers
@@ -430,12 +431,23 @@
 		expect it to be in bytes, others in MB.
 		Define CONFIG_MEMSIZE_IN_BYTES to make it in bytes.
 
-		CONFIG_OF_FLAT_TREE
+		CONFIG_OF_LIBFDT / CONFIG_OF_FLAT_TREE
 
 		New kernel versions are expecting firmware settings to be
-		passed using flat open firmware trees.
-		The environment variable "disable_of", when set, disables this
-		functionality.
+		passed using flattened device trees (based on open firmware
+		concepts).
+
+		CONFIG_OF_LIBFDT
+		 * New libfdt-based support
+		 * Adds the "fdt" command
+		 * The bootm command does _not_ modify the fdt
+
+		CONFIG_OF_FLAT_TREE
+		 * Deprecated, see CONFIG_OF_LIBFDT
+		 * Original ft_build.c-based support
+		 * Automatically modifies the dft as part of the bootm command
+		 * The environment variable "disable_of", when set,
+		     disables this functionality.
 
 		CONFIG_OF_FLAT_TREE_MAX_SIZE
 
@@ -448,13 +460,16 @@
 
 		CONFIG_OF_HAS_BD_T
 
-		The resulting flat device tree will have a copy of the bd_t.
-		Space should be pre-allocated in the dts for the bd_t.
+		 * CONFIG_OF_LIBFDT - enables the "fdt bd_t" command
+		 * CONFIG_OF_FLAT_TREE - The resulting flat device tree
+		     will have a copy of the bd_t.  Space should be
+		     pre-allocated in the dts for the bd_t.
 
 		CONFIG_OF_HAS_UBOOT_ENV
 
-		The resulting flat device tree will have a copy of u-boot's
-		environment variables
+		 * CONFIG_OF_LIBFDT - enables the "fdt bd_t" command
+		 * CONFIG_OF_FLAT_TREE - The resulting flat device tree
+		     will have a copy of u-boot's environment variables
 
 		CONFIG_OF_BOARD_SETUP
 
@@ -721,6 +736,8 @@
 
 		#define CONFIG_COMMANDS (CFG_CMD_ALL & ~CFG_CMD_NET)
 
+	Other Commands:
+		fdt (flattened device tree) command: CONFIG_OF_LIBFDT
 
 	Note:	Don't enable the "icache" and "dcache" commands
 		(configuration option CFG_CMD_CACHE) unless you know
diff --git a/board/AtmarkTechno/suzaku/suzaku.c b/board/AtmarkTechno/suzaku/suzaku.c
index afe124a..267c476 100644
--- a/board/AtmarkTechno/suzaku/suzaku.c
+++ b/board/AtmarkTechno/suzaku/suzaku.c
@@ -24,7 +24,7 @@
 
 /* This is a board specific file.  It's OK to include board specific
  * header files */
-#include <asm/suzaku.h>
+#include <config.h>
 
 void do_reset(void)
 {
diff --git a/board/AtmarkTechno/suzaku/u-boot.lds b/board/AtmarkTechno/suzaku/u-boot.lds
index 00a8ef7..cb90854 100644
--- a/board/AtmarkTechno/suzaku/u-boot.lds
+++ b/board/AtmarkTechno/suzaku/u-boot.lds
@@ -61,6 +61,7 @@
 	{
 		__bss_start = .;
 		*(.bss)
-		__bss_start = .;
+		__bss_end = .;
 	}
+	__end = . ;
 }
diff --git a/board/mpc8360emds/config.mk b/board/mpc8360emds/config.mk
index 9ace886..5801a5f 100644
--- a/board/mpc8360emds/config.mk
+++ b/board/mpc8360emds/config.mk
@@ -26,3 +26,8 @@
 #
 
 TEXT_BASE = 0xFE000000
+
+#
+# Additional board-specific libraries
+#
+BOARDLIBS = libfdt/libfdt.a
diff --git a/board/mpc8360emds/mpc8360emds.c b/board/mpc8360emds/mpc8360emds.c
index 535884c..deadb5f 100644
--- a/board/mpc8360emds/mpc8360emds.c
+++ b/board/mpc8360emds/mpc8360emds.c
@@ -31,6 +31,10 @@
 #if defined(CONFIG_OF_FLAT_TREE)
 #include <ft_build.h>
 #endif
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
+#endif
 
 const qe_iop_conf_t qe_iop_conf_tab[] = {
 	/* GETH1 */
@@ -658,22 +662,36 @@
 	   "  - disables injects\n" "  - re-inits memory");
 #endif				/* if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD) */
 
-#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP)
+#if (defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)) \
+     && defined(CONFIG_OF_BOARD_SETUP)
 void
 ft_board_setup(void *blob, bd_t *bd)
 {
+#if defined(CONFIG_OF_LIBFDT)
+	int nodeoffset;
+	int err;
+	int tmp[2];
+
+	nodeoffset = fdt_path_offset (fdt, "/memory");
+	if (nodeoffset >= 0) {
+		tmp[0] = cpu_to_be32(bd->bi_memstart);
+		tmp[1] = cpu_to_be32(bd->bi_memsize);
+		err = fdt_setprop(fdt, nodeoffset, "reg", tmp, sizeof(tmp));
+	}
+#else
 	u32 *p;
 	int len;
 
-#ifdef CONFIG_PCI
-	ft_pci_setup(blob, bd);
-#endif
-	ft_cpu_setup(blob, bd);
-
 	p = ft_get_prop(blob, "/memory/reg", &len);
 	if (p != NULL) {
 		*p++ = cpu_to_be32(bd->bi_memstart);
 		*p = cpu_to_be32(bd->bi_memsize);
 	}
+#endif
+
+#ifdef CONFIG_PCI
+	ft_pci_setup(blob, bd);
+#endif
+	ft_cpu_setup(blob, bd);
 }
 #endif
diff --git a/board/mpc8360emds/pci.c b/board/mpc8360emds/pci.c
index 67cd709..158effe 100644
--- a/board/mpc8360emds/pci.c
+++ b/board/mpc8360emds/pci.c
@@ -21,6 +21,10 @@
 #if defined(CONFIG_OF_FLAT_TREE)
 #include <ft_build.h>
 #endif
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
+#endif
 
 #include <asm/fsl_i2c.h>
 
@@ -299,6 +303,22 @@
 }
 #endif				/* CONFIG_PCISLAVE */
 
+#if defined(CONFIG_OF_LIBFDT)
+void
+ft_pci_setup(void *blob, bd_t *bd)
+{
+	int nodeoffset;
+	int err;
+	int tmp[2];
+
+	nodeoffset = fdt_path_offset (fdt, "/" OF_SOC "/pci@8500");
+	if (nodeoffset >= 0) {
+		tmp[0] = cpu_to_be32(hose[0].first_busno);
+		tmp[1] = cpu_to_be32(hose[0].last_busno);
+		err = fdt_setprop(fdt, nodeoffset, "bus-range", tmp, sizeof(tmp));
+	}
+}
+#endif				/* CONFIG_OF_LIBFDT */
 #ifdef CONFIG_OF_FLAT_TREE
 void
 ft_pci_setup(void *blob, bd_t *bd)
diff --git a/board/xilinx/ml401/Makefile b/board/xilinx/ml401/Makefile
new file mode 100644
index 0000000..9ab5633
--- /dev/null
+++ b/board/xilinx/ml401/Makefile
@@ -0,0 +1,65 @@
+#
+# (C) Copyright 2000-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
+ifneq ($(OBJTREE),$(SRCTREE))
+$(shell mkdir -p $(obj)../common)
+$(shell mkdir -p $(obj)../xilinx_enet)
+endif
+
+INCS		:= -I../common -I../xilinx_enet
+CFLAGS		+= $(INCS)
+HOST_CFLAGS	+= $(INCS)
+
+LIB	= $(obj)lib$(BOARD).a
+
+COBJS	= $(BOARD).o \
+	  ../xilinx_enet/emac_adapter.o  ../xilinx_enet/xemac.o \
+	  ../xilinx_enet/xemac_options.o ../xilinx_enet/xemac_polled.o \
+	  ../xilinx_enet/xemac_intr.o ../xilinx_enet/xemac_g.o \
+	  ../xilinx_enet/xemac_intr_dma.o ../common/xipif_v1_23_b.o \
+	  ../common/xbasic_types.o ../common/xdma_channel.o \
+	  ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \
+	  ../common/xversion.o \
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $^
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/xilinx/ml401/config.mk b/board/xilinx/ml401/config.mk
new file mode 100644
index 0000000..807f169
--- /dev/null
+++ b/board/xilinx/ml401/config.mk
@@ -0,0 +1,32 @@
+#
+# (C) Copyright 2007 Michal Simek
+#
+# Michal  SIMEK <monstr@monstr.eu>
+#
+# 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
+#
+# CAUTION: This file is automatically generated by libgen.
+# Version: Xilinx EDK 6.3 EDK_Gmm.12.3
+#
+
+TEXT_BASE = 0x12000000
+
+PLATFORM_CPPFLAGS += -mno-xl-soft-mul
+PLATFORM_CPPFLAGS += -mno-xl-soft-div
+PLATFORM_CPPFLAGS += -mxl-barrel-shift
diff --git a/board/xilinx/ml401/ml401.c b/board/xilinx/ml401/ml401.c
new file mode 100644
index 0000000..b48103f
--- /dev/null
+++ b/board/xilinx/ml401/ml401.c
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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
+ */
+
+/* This is a board specific file.  It's OK to include board specific
+ * header files */
+
+#include <common.h>
+#include <config.h>
+
+void do_reset (void)
+{
+#ifdef CFG_GPIO_0
+	*((unsigned long *)(CFG_GPIO_0_ADDR)) =
+	    ++(*((unsigned long *)(CFG_GPIO_0_ADDR)));
+#endif
+#ifdef CFG_RESET_ADDRESS
+	puts ("Reseting board\n");
+	asm ("bra r0");
+#endif
+}
+
+int gpio_init (void)
+{
+#ifdef CFG_GPIO_0
+	*((unsigned long *)(CFG_GPIO_0_ADDR)) = 0x0;
+#endif
+	return 0;
+}
diff --git a/include/asm-microblaze/platform.h b/board/xilinx/ml401/u-boot.lds
similarity index 63%
copy from include/asm-microblaze/platform.h
copy to board/xilinx/ml401/u-boot.lds
index 2096cce..cb90854 100644
--- a/include/asm-microblaze/platform.h
+++ b/board/xilinx/ml401/u-boot.lds
@@ -22,8 +22,46 @@
  * MA 02111-1307 USA
  */
 
-#include <config.h>
+OUTPUT_ARCH(microblaze)
+ENTRY(_start)
 
-#ifdef CONFIG_SUZAKU
-#include <asm/suzaku.h>
-#endif
+SECTIONS
+{
+	.text ALIGN(0x4):
+	{
+		__text_start = .;
+		cpu/microblaze/start.o (.text)
+		*(.text)
+		__text_end = .;
+	}
+
+	.rodata ALIGN(0x4):
+	{
+		__rodata_start = .;
+		*(.rodata)
+		__rodata_end = .;
+	}
+
+	.data ALIGN(0x4):
+	{
+		__data_start = .;
+		*(.data)
+		__data_end = .;
+	}
+
+	.u_boot_cmd ALIGN(0x4):
+	{
+		. = .;
+		__u_boot_cmd_start = .;
+		*(.u_boot_cmd)
+		__u_boot_cmd_end = .;
+	}
+
+	.bss ALIGN(0x4):
+	{
+		__bss_start = .;
+		*(.bss)
+		__bss_end = .;
+	}
+	__end = . ;
+}
diff --git a/board/xilinx/ml401/xparameters.h b/board/xilinx/ml401/xparameters.h
new file mode 100644
index 0000000..18d24f9
--- /dev/null
+++ b/board/xilinx/ml401/xparameters.h
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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
+ *
+ *
+ * CAUTION: This file is automatically generated by libgen.
+ * Version: Xilinx EDK 6.3 EDK_Gmm.12.3
+ */
+
+/* System Clock Frequency */
+#define XILINX_CLOCK_FREQ	66666667
+
+/* Interrupt controller is intc_0 */
+#define XILINX_INTC_BASEADDR	0xd1000fc0
+#define XILINX_INTC_NUM_INTR_INPUTS	12
+
+/* Timer pheriphery is opb_timer_0 */
+#define XILINX_TIMER_BASEADDR	0xa2000000
+#define XILINX_TIMER_IRQ	0
+
+/* Uart pheriphery is console_uart */
+#define XILINX_UART_BASEADDR	0xa0000000
+#define XILINX_UART_BAUDRATE	115200
+
+/* GPIO is opb_gpio_0*/
+#define XILINX_GPIO_BASEADDR	0x90000000
+
+/* Flash Memory is opb_emc_0 */
+#define XILINX_FLASH_START	0x28000000
+#define XILINX_FLASH_SIZE	0x00800000
+
+/* Main Memory is plb_ddr_0 */
+#define XILINX_RAM_START	0x10000000
+#define XILINX_RAM_SIZE	0x10000000
+
+/* Sysace Controller is opb_sysace_0 */
+#define XILINX_SYSACE_BASEADDR	0xCF000000
+#define XILINX_SYSACE_HIGHADDR	0xCF0001FF
+#define XILINX_SYSACE_MEM_WIDTH	16
+
+/* Ethernet controller is opb_ethernet_0 */
+#define XPAR_XEMAC_NUM_INSTANCES	1
+#define XPAR_OPB_ETHERNET_0_DEVICE_ID	0
+#define XPAR_OPB_ETHERNET_0_BASEADDR	0x60000000
+#define XPAR_OPB_ETHERNET_0_HIGHADDR	0x60003FFF
+#define XPAR_OPB_ETHERNET_0_DMA_PRESENT	1
+#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST	1
+#define XPAR_OPB_ETHERNET_0_MII_EXIST	1
diff --git a/board/xilinx/xilinx_enet/emac_adapter.c b/board/xilinx/xilinx_enet/emac_adapter.c
index f159cb6..d340303 100644
--- a/board/xilinx/xilinx_enet/emac_adapter.c
+++ b/board/xilinx/xilinx_enet/emac_adapter.c
@@ -147,7 +147,11 @@
 	RecvFrameLength = PKTSIZE;
 	Result = XEmac_PollRecv(&Emac, (u8 *) etherrxbuff, &RecvFrameLength);
 	if (Result == XST_SUCCESS) {
+#ifndef CONFIG_EMACLITE
 		NetReceive((uchar *)etherrxbuff, RecvFrameLength);
+#else
+		NetReceive(etherrxbuff, RecvFrameLength);
+#endif
 		return (1);
 	} else {
 		return (0);
diff --git a/board/xilinx/xupv2p/Makefile b/board/xilinx/xupv2p/Makefile
new file mode 100644
index 0000000..9ab5633
--- /dev/null
+++ b/board/xilinx/xupv2p/Makefile
@@ -0,0 +1,65 @@
+#
+# (C) Copyright 2000-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
+ifneq ($(OBJTREE),$(SRCTREE))
+$(shell mkdir -p $(obj)../common)
+$(shell mkdir -p $(obj)../xilinx_enet)
+endif
+
+INCS		:= -I../common -I../xilinx_enet
+CFLAGS		+= $(INCS)
+HOST_CFLAGS	+= $(INCS)
+
+LIB	= $(obj)lib$(BOARD).a
+
+COBJS	= $(BOARD).o \
+	  ../xilinx_enet/emac_adapter.o  ../xilinx_enet/xemac.o \
+	  ../xilinx_enet/xemac_options.o ../xilinx_enet/xemac_polled.o \
+	  ../xilinx_enet/xemac_intr.o ../xilinx_enet/xemac_g.o \
+	  ../xilinx_enet/xemac_intr_dma.o ../common/xipif_v1_23_b.o \
+	  ../common/xbasic_types.o ../common/xdma_channel.o \
+	  ../common/xdma_channel_sg.o ../common/xpacket_fifo_v1_00_b.o \
+	  ../common/xversion.o \
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(OBJS) $(SOBJS)
+	$(AR) $(ARFLAGS) $@ $^
+
+clean:
+	rm -f $(SOBJS) $(OBJS)
+
+distclean:	clean
+	rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/xilinx/xupv2p/config.mk b/board/xilinx/xupv2p/config.mk
new file mode 100644
index 0000000..c07b0b3
--- /dev/null
+++ b/board/xilinx/xupv2p/config.mk
@@ -0,0 +1,32 @@
+#
+# (C) Copyright 2007 Michal Simek
+#
+# Michal  SIMEK <monstr@monstr.eu>
+#
+# 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
+#
+# CAUTION: This file is automatically generated by libgen.
+# Version: Xilinx EDK 8.2.02 EDK_Im_Sp2.4
+#
+
+TEXT_BASE = 0x38000000
+
+PLATFORM_CPPFLAGS += -mno-xl-soft-mul
+PLATFORM_CPPFLAGS += -mno-xl-soft-div
+PLATFORM_CPPFLAGS += -mxl-barrel-shift
diff --git a/include/asm-microblaze/platform.h b/board/xilinx/xupv2p/u-boot.lds
similarity index 63%
copy from include/asm-microblaze/platform.h
copy to board/xilinx/xupv2p/u-boot.lds
index 2096cce..cb90854 100644
--- a/include/asm-microblaze/platform.h
+++ b/board/xilinx/xupv2p/u-boot.lds
@@ -22,8 +22,46 @@
  * MA 02111-1307 USA
  */
 
-#include <config.h>
+OUTPUT_ARCH(microblaze)
+ENTRY(_start)
 
-#ifdef CONFIG_SUZAKU
-#include <asm/suzaku.h>
-#endif
+SECTIONS
+{
+	.text ALIGN(0x4):
+	{
+		__text_start = .;
+		cpu/microblaze/start.o (.text)
+		*(.text)
+		__text_end = .;
+	}
+
+	.rodata ALIGN(0x4):
+	{
+		__rodata_start = .;
+		*(.rodata)
+		__rodata_end = .;
+	}
+
+	.data ALIGN(0x4):
+	{
+		__data_start = .;
+		*(.data)
+		__data_end = .;
+	}
+
+	.u_boot_cmd ALIGN(0x4):
+	{
+		. = .;
+		__u_boot_cmd_start = .;
+		*(.u_boot_cmd)
+		__u_boot_cmd_end = .;
+	}
+
+	.bss ALIGN(0x4):
+	{
+		__bss_start = .;
+		*(.bss)
+		__bss_end = .;
+	}
+	__end = . ;
+}
diff --git a/board/xilinx/xupv2p/xparameters.h b/board/xilinx/xupv2p/xparameters.h
new file mode 100644
index 0000000..a96c693
--- /dev/null
+++ b/board/xilinx/xupv2p/xparameters.h
@@ -0,0 +1,64 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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
+ *
+ * CAUTION: This file is automatically generated by libgen.
+ * Version: Xilinx EDK 8.2.02 EDK_Im_Sp2.4
+ */
+
+/* System Clock Frequency */
+#define XILINX_CLOCK_FREQ	100000000
+
+/* Interrupt controller is opb_intc_0 */
+#define XILINX_INTC_BASEADDR	0x41200000
+#define XILINX_INTC_NUM_INTR_INPUTS	11
+
+/* Timer pheriphery is opb_timer_1 */
+#define XILINX_TIMER_BASEADDR	0x41c00000
+#define XILINX_TIMER_IRQ	1
+
+/* Uart pheriphery is RS232_Uart_1 */
+#define XILINX_UART_BASEADDR	0x40600000
+#define XILINX_UART_BAUDRATE	115200
+
+/* GPIO is LEDs_4Bit*/
+#define XILINX_GPIO_BASEADDR	0x40000000
+
+/* FLASH doesn't exist none */
+
+/* Main Memory is DDR_256MB_32MX64_rank1_row13_col10_cl2_5 */
+#define XILINX_RAM_START	0x30000000
+#define XILINX_RAM_SIZE	0x10000000
+
+/* Sysace Controller is SysACE_CompactFlash */
+#define XILINX_SYSACE_BASEADDR	0x41800000
+#define XILINX_SYSACE_HIGHADDR	0x4180ffff
+#define XILINX_SYSACE_MEM_WIDTH	16
+
+/* Ethernet controller is Ethernet_MAC */
+#define XPAR_XEMAC_NUM_INSTANCES	1
+#define XPAR_OPB_ETHERNET_0_DEVICE_ID	0
+#define XPAR_OPB_ETHERNET_0_BASEADDR	0x40c00000
+#define XPAR_OPB_ETHERNET_0_HIGHADDR	0x40c0ffff
+#define XPAR_OPB_ETHERNET_0_DMA_PRESENT	1
+#define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST	1
+#define XPAR_OPB_ETHERNET_0_MII_EXIST	1
diff --git a/board/xilinx/xupv2p/xupv2p.c b/board/xilinx/xupv2p/xupv2p.c
new file mode 100644
index 0000000..b48103f
--- /dev/null
+++ b/board/xilinx/xupv2p/xupv2p.c
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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
+ */
+
+/* This is a board specific file.  It's OK to include board specific
+ * header files */
+
+#include <common.h>
+#include <config.h>
+
+void do_reset (void)
+{
+#ifdef CFG_GPIO_0
+	*((unsigned long *)(CFG_GPIO_0_ADDR)) =
+	    ++(*((unsigned long *)(CFG_GPIO_0_ADDR)));
+#endif
+#ifdef CFG_RESET_ADDRESS
+	puts ("Reseting board\n");
+	asm ("bra r0");
+#endif
+}
+
+int gpio_init (void)
+{
+#ifdef CFG_GPIO_0
+	*((unsigned long *)(CFG_GPIO_0_ADDR)) = 0x0;
+#endif
+	return 0;
+}
diff --git a/common/Makefile b/common/Makefile
index 6f81c4a..74a6af2 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -32,7 +32,7 @@
 	  cmd_cache.o cmd_console.o \
 	  cmd_date.o cmd_dcr.o cmd_diag.o cmd_display.o cmd_doc.o cmd_dtt.o \
 	  cmd_eeprom.o cmd_elf.o cmd_ext2.o \
-	  cmd_fat.o cmd_fdc.o cmd_fdos.o cmd_flash.o cmd_fpga.o \
+	  cmd_fat.o cmd_fdc.o cmd_fdt.o cmd_fdos.o cmd_flash.o cmd_fpga.o \
 	  cmd_i2c.o cmd_ide.o cmd_immap.o cmd_itest.o cmd_jffs2.o \
 	  cmd_load.o cmd_log.o \
 	  cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index 70de795..d97c09e 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -180,6 +180,32 @@
 
 	return 0;
 }
+#elif defined(CONFIG_MICROBLAZE) /* ! PPC, which leaves Microblaze */
+
+int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	int i;
+	bd_t *bd = gd->bd;
+	print_num ("mem start      ",	(ulong)bd->bi_memstart);
+	print_num ("mem size       ",	(ulong)bd->bi_memsize);
+	print_num ("flash start    ",	(ulong)bd->bi_flashstart);
+	print_num ("flash size     ",	(ulong)bd->bi_flashsize);
+	print_num ("flash offset   ",	(ulong)bd->bi_flashoffset);
+#if defined(CFG_SRAM_BASE)
+	print_num ("sram start     ",	(ulong)bd->bi_sramstart);
+	print_num ("sram size      ",	(ulong)bd->bi_sramsize);
+#endif
+#if defined(CFG_CMD_NET)
+	puts ("ethaddr     =");
+	for (i=0; i<6; ++i) {
+		printf ("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]);
+	}
+	puts ("\nip_addr     = ");
+	print_IPaddr (bd->bi_ip_addr);
+#endif
+	printf ("\nbaudrate    = %d bps\n", (ulong)bd->bi_baudrate);
+	return 0;
+}
 
 #else /* ! PPC, which leaves MIPS */
 
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index c0ed076..2721216b 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -34,7 +34,11 @@
 #include <environment.h>
 #include <asm/byteorder.h>
 
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_LIBFDT)
+#include <fdt.h>
+#include <libfdt.h>
+#endif
+#if defined(CONFIG_OF_FLAT_TREE)
 #include <ft_build.h>
 #endif
 
@@ -467,7 +471,7 @@
  	"[addr [arg ...]]\n    - boot application image stored in memory\n"
  	"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
  	"\t'arg' can be the address of an initrd image\n"
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
 	"\tWhen booting a Linux kernel which requires a flat device-tree\n"
 	"\ta third argument is required which is the address of the of the\n"
 	"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
@@ -529,7 +533,7 @@
 	bd_t	*kbd;
 	void	(*kernel)(bd_t *, ulong, ulong, ulong, ulong);
 	image_header_t *hdr = &header;
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
 	char	*of_flat_tree = NULL;
 	ulong	of_data = 0;
 #endif
@@ -622,7 +626,7 @@
 	 * Check if there is an initrd image
 	 */
 
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
 	/* Look for a '-' which indicates to ignore the ramdisk argument */
 	if (argc >= 3 && strcmp(argv[2], "-") ==  0) {
 			debug ("Skipping initrd\n");
@@ -739,12 +743,15 @@
 		len = data = 0;
 	}
 
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
 	if(argc > 3) {
 		of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16);
 		hdr = (image_header_t *)of_flat_tree;
-
-		if  (*(ulong *)of_flat_tree == OF_DT_HEADER) {
+#if defined(CONFIG_OF_LIBFDT)
+		if (be32_to_cpu(fdt_magic(of_flat_tree)) == FDT_MAGIC) {
+#else
+		if (*(ulong *)of_flat_tree == OF_DT_HEADER) {
+#endif
 #ifndef CFG_NO_FLASH
 			if (addr2info((ulong)of_flat_tree) != NULL)
 				of_data = (ulong)of_flat_tree;
@@ -787,7 +794,11 @@
 				printf("ERROR: uImage is not uncompressed\n");
 				return;
 			}
+#if defined(CONFIG_OF_LIBFDT)
+			if (be32_to_cpu(fdt_magic(of_flat_tree + sizeof(image_header_t))) != FDT_MAGIC) {
+#else
 			if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {
+#endif
 				printf ("ERROR: uImage data is not a flat device tree\n");
 				return;
 			}
@@ -824,12 +835,20 @@
 			of_data += 4 - tail;
 		}
 
+#if defined(CONFIG_OF_LIBFDT)
+		if (be32_to_cpu(fdt_magic(of_data)) != FDT_MAGIC) {
+#else
 		if (((struct boot_param_header *)of_data)->magic != OF_DT_HEADER) {
+#endif
 			printf ("ERROR: image is not a flat device tree\n");
 			return;
 		}
 
+#if defined(CONFIG_OF_LIBFDT)
+		if (be32_to_cpu(fdt_totalsize(of_data)) !=  ntohl(len_ptr[2])) {
+#else
 		if (((struct boot_param_header *)of_data)->totalsize != ntohl(len_ptr[2])) {
+#endif
 			printf ("ERROR: flat device tree size does not agree with image\n");
 			return;
 		}
@@ -913,7 +932,31 @@
 	unlock_ram_in_cache();
 #endif
 
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_LIBFDT)
+	/* move of_flat_tree if needed */
+	if (of_data) {
+		int err;
+		ulong of_start, of_len;
+		of_len = be32_to_cpu(fdt_totalsize(of_data));
+		/* provide extra 8k pad */
+		if (initrd_start)
+			of_start = initrd_start - of_len - 8192;
+		else
+			of_start  = (ulong)kbd - of_len - 8192;
+		of_start &= ~(4096 - 1);	/* align on page */
+		debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n",
+			of_data, of_data + of_len - 1, of_len, of_len);
+
+
+		printf ("   Loading Device Tree to %08lx, end %08lx ... ",
+			of_start, of_start + of_len - 1);
+		err = fdt_open_into(of_start, of_data, of_len);
+		if (err != 0) {
+			printf ("libfdt: %s\n", fdt_strerror(err));
+		}
+	}
+#endif
+#if defined(CONFIG_OF_FLAT_TREE)
 	/* move of_flat_tree if needed */
 	if (of_data) {
 		ulong of_start, of_len;
@@ -942,13 +985,13 @@
 	 *   r6: Start of command line string
 	 *   r7: End   of command line string
 	 */
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
 	if (!of_flat_tree)	/* no device tree; boot old style */
 #endif
 		(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
 		/* does not return */
 
-#ifdef CONFIG_OF_FLAT_TREE
+#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
 	/*
 	 * Linux Kernel Parameters (passing device tree):
 	 *   r3: ptr to OF flat tree, followed by the board info data
@@ -957,8 +1000,10 @@
 	 *   r6: NULL
 	 *   r7: NULL
 	 */
+#if defined(CONFIG_OF_FLAT_TREE)
 	ft_setup(of_flat_tree, kbd, initrd_start, initrd_end);
 	/* ft_dump_blob(of_flat_tree); */
+#endif
 
 	(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
 #endif
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
new file mode 100644
index 0000000..968bade
--- /dev/null
+++ b/common/cmd_fdt.c
@@ -0,0 +1,874 @@
+/*
+ * (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ * Based on code written by:
+ *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
+ *   Matthew McClintock <msm@freescale.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 <command.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_OF_LIBFDT
+#include <asm/global_data.h>
+#include <fdt.h>
+#include <libfdt.h>
+
+#define MAX_LEVEL	32		/* how deeply nested we will go */
+#define SCRATCHPAD	1024	/* bytes of scratchpad memory */
+
+/*
+ * Global data (for the gd->bd)
+ */
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Scratchpad memory.
+ */
+static char data[SCRATCHPAD];
+
+
+/*
+ * Function prototypes/declarations.
+ */
+static int fdt_valid(void);
+static void print_data(const void *data, int len);
+static int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end);
+static int fdt_env(void *fdt);
+static int fdt_bd_t(void *fdt);
+
+
+/*
+ * Flattened Device Tree command, see the help for parameter definitions.
+ */
+int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	char		op;
+
+	if (argc < 2) {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	/*
+	 * Figure out which subcommand was given
+	 */
+	op = argv[1][0];
+	/********************************************************************
+	 * Set the address of the fdt
+	 ********************************************************************/
+	if (op == 'a') {
+		/*
+		 * Set the address [and length] of the fdt.
+		 */
+		fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
+
+		if (!fdt_valid()) {
+			return 1;
+		}
+
+		if (argc >= 4) {
+			int  len;
+			int  err;
+			/*
+			 * Optional new length
+			 */
+			len =  simple_strtoul(argv[3], NULL, 16);
+			if (len < fdt_totalsize(fdt)) {
+				printf ("New length %d < existing length %d, ignoring.\n",
+					len, fdt_totalsize(fdt));
+			} else {
+				/*
+				 * Open in place with a new length.
+				 */
+				err = fdt_open_into(fdt, fdt, len);
+				if (err != 0) {
+					printf ("libfdt: %s\n", fdt_strerror(err));
+				}
+			}
+		}
+
+	/********************************************************************
+	 * Move the fdt
+	 ********************************************************************/
+	} else if (op == 'm') {
+		struct fdt_header *newaddr;
+		int  len;
+		int  err;
+
+		if (argc != 5) {
+			printf ("Usage:\n%s\n", cmdtp->usage);
+			return 1;
+		}
+
+		/*
+		 * Set the address and length of the fdt.
+		 */
+		fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
+		if (!fdt_valid()) {
+			return 1;
+		}
+
+		newaddr = (struct fdt_header *)simple_strtoul(argv[3], NULL, 16);
+		len     =  simple_strtoul(argv[4], NULL, 16);
+		if (len < fdt_totalsize(fdt)) {
+			printf ("New length %d < existing length %d, aborting.\n",
+				len, fdt_totalsize(fdt));
+			return 1;
+		}
+
+		/*
+		 * Copy to the new location.
+		 */
+		err = fdt_open_into(fdt, newaddr, len);
+		if (err != 0) {
+			printf ("libfdt: %s\n", fdt_strerror(err));
+			return 1;
+		}
+		fdt = newaddr;
+
+	/********************************************************************
+	 * Set the value of a node in the fdt.
+	 ********************************************************************/
+	} else if (op == 's') {
+		char *pathp;		/* path */
+		char *prop;			/* property */
+		struct fdt_property *nodep;	/* node struct pointer */
+		char *newval;		/* value from the user (as a string) */
+		char *vp;			/* temporary value pointer */
+		char *cp;			/* temporary char pointer */
+		int  nodeoffset;	/* node offset from libfdt */
+		int  len;			/* new length of the property */
+		int  oldlen;		/* original length of the property */
+		unsigned long tmp;	/* holds converted values */
+		int  ret;			/* return value */
+
+		/*
+		 * Parameters: Node path, property, value.
+		 */
+		if (argc < 5) {
+			printf ("Usage:\n%s\n", cmdtp->usage);
+			return 1;
+		}
+
+		pathp  = argv[2];
+		prop   = argv[3];
+		newval = argv[4];
+
+		if (strcmp(pathp, "/") == 0) {
+			nodeoffset = 0;
+		} else {
+			nodeoffset = fdt_path_offset (fdt, pathp);
+			if (nodeoffset < 0) {
+				/*
+			 	 * Not found or something else bad happened.
+			 	 */
+				printf ("libfdt: %s\n", fdt_strerror(nodeoffset));
+				return 1;
+			}
+		}
+		nodep = fdt_getprop (fdt, nodeoffset, prop, &oldlen);
+		if (oldlen < 0) {
+			printf ("libfdt %s\n", fdt_strerror(oldlen));
+			return 1;
+		} else if (oldlen == 0) {
+			/*
+			 * The specified property has no value
+			 */
+			printf("%s has no value, cannot set one (yet).\n", prop);
+			return 1;
+		} else {
+			/*
+			 * Convert the new property
+			 */
+			vp = data;
+			if (*newval == '<') {
+				/*
+				 * Bigger values than bytes.
+				 */
+				len = 0;
+				newval++;
+				while ((*newval != '>') && (*newval != '\0')) {
+					cp = newval;
+					tmp = simple_strtoul(cp, &newval, 16);
+					if ((newval - cp) <= 2) {
+						*vp = tmp & 0xFF;
+						vp  += 1;
+						len += 1;
+					} else if ((newval - cp) <= 4) {
+						*(uint16_t *)vp = __cpu_to_be16(tmp);
+						vp  += 2;
+						len += 2;
+					} else if ((newval - cp) <= 8) {
+						*(uint32_t *)vp = __cpu_to_be32(tmp);
+						vp  += 4;
+						len += 4;
+					} else {
+						printf("Sorry, I could not convert \"%s\"\n", cp);
+						return 1;
+					}
+					while (*newval == ' ')
+						newval++;
+				}
+				if (*newval != '>') {
+					printf("Unexpected character '%c'\n", *newval);
+					return 1;
+				}
+			} else if (*newval == '[') {
+				/*
+				 * Byte stream.  Convert the values.
+				 */
+				len = 0;
+				newval++;
+				while ((*newval != ']') && (*newval != '\0')) {
+					tmp = simple_strtoul(newval, &newval, 16);
+					*vp++ = tmp & 0xFF;
+					len++;
+					while (*newval == ' ')
+						newval++;
+				}
+				if (*newval != ']') {
+					printf("Unexpected character '%c'\n", *newval);
+					return 1;
+				}
+			} else {
+				/*
+				 * Assume it is a string.  Copy it into our data area for
+				 * convenience (including the terminating '\0').
+				 */
+				len = strlen(newval) + 1;
+				strcpy(data, newval);
+			}
+
+			ret = fdt_setprop(fdt, nodeoffset, prop, data, len);
+			if (ret < 0) {
+				printf ("libfdt %s\n", fdt_strerror(ret));
+				return 1;
+			}
+		}
+
+	/********************************************************************
+	 * Print (recursive) / List (single level)
+	 ********************************************************************/
+	} else if ((op == 'p') || (op == 'l')) {
+		/*
+		 * Recursively print (a portion of) the fdt.
+		 */
+		static int offstack[MAX_LEVEL];
+		static char tabs[MAX_LEVEL+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+		int depth = MAX_LEVEL;	/* how deep to print */
+		char *pathp;		/* path */
+		char *prop;			/* property */
+		void *nodep;		/* property node pointer */
+		int  nodeoffset;	/* node offset from libfdt */
+		int  nextoffset;	/* next node offset from libfdt */
+		uint32_t tag;		/* tag */
+		int  len;			/* length of the property */
+		int  level = 0;		/* keep track of nesting level */
+
+		/*
+		 * list is an alias for print, but limited to 1 level
+		 */
+		if (op == 'l') {
+			depth = 1;
+		}
+
+		/*
+		 * Get the starting path.  The root node is an oddball,
+		 * the offset is zero and has no name.
+		 */
+		pathp = argv[2];
+		if (argc > 3)
+			prop = argv[3];
+		else
+			prop = NULL;
+
+		if (strcmp(pathp, "/") == 0) {
+			nodeoffset = 0;
+			printf("/");
+		} else {
+			nodeoffset = fdt_path_offset (fdt, pathp);
+			if (nodeoffset < 0) {
+				/*
+				 * Not found or something else bad happened.
+				 */
+				printf ("libfdt %s\n", fdt_strerror(nodeoffset));
+				return 1;
+			}
+		}
+		/*
+		 * The user passed in a property as well as node path.  Print only
+		 * the given property and then return.
+		 */
+		if (prop) {
+			nodep = fdt_getprop (fdt, nodeoffset, prop, &len);
+			if (len == 0) {
+				printf("%s %s\n", pathp, prop);	/* no property value */
+				return 0;
+			} else if (len > 0) {
+				printf("%s=", prop);
+				print_data (nodep, len);
+				printf("\n");
+				return 0;
+			} else {
+				printf ("libfdt %s\n", fdt_strerror(len));
+				return 1;
+			}
+		}
+
+		/*
+		 * The user passed in a node path and no property, print the node
+		 * and all subnodes.
+		 */
+		offstack[0] = nodeoffset;
+
+		while(level >= 0) {
+			tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, &pathp);
+			switch(tag) {
+			case FDT_BEGIN_NODE:
+				if(level <= depth)
+					printf("%s%s {\n", &tabs[MAX_LEVEL - level], pathp);
+				level++;
+				offstack[level] = nodeoffset;
+				if (level >= MAX_LEVEL) {
+					printf("Aaaiii <splat> nested too deep.\n");
+					return 1;
+				}
+				break;
+			case FDT_END_NODE:
+				level--;
+				if(level <= depth)
+					printf("%s};\n", &tabs[MAX_LEVEL - level]);
+				if (level == 0) {
+					level = -1;		/* exit the loop */
+				}
+				break;
+			case FDT_PROP:
+				nodep = fdt_getprop (fdt, offstack[level], pathp, &len);
+				if (len < 0) {
+					printf ("libfdt %s\n", fdt_strerror(len));
+					return 1;
+				} else if (len == 0) {
+					/* the property has no value */
+					if(level <= depth)
+						printf("%s%s;\n", &tabs[MAX_LEVEL - level], pathp);
+				} else {
+					if(level <= depth) {
+						printf("%s%s=", &tabs[MAX_LEVEL - level], pathp);
+						print_data (nodep, len);
+						printf(";\n");
+					}
+				}
+				break;
+			case FDT_NOP:
+				break;
+			case FDT_END:
+				return 1;
+			default:
+				if(level <= depth)
+					printf("Unknown tag 0x%08X\n", tag);
+				return 1;
+			}
+			nodeoffset = nextoffset;
+		}
+
+	/********************************************************************
+	 * Remove a property/node
+	 ********************************************************************/
+	} else if (op == 'r') {
+		int  nodeoffset;	/* node offset from libfdt */
+		int  err;
+
+		/*
+		 * Get the path.  The root node is an oddball, the offset
+		 * is zero and has no name.
+		 */
+		if (strcmp(argv[2], "/") == 0) {
+			nodeoffset = 0;
+		} else {
+			nodeoffset = fdt_path_offset (fdt, argv[2]);
+			if (nodeoffset < 0) {
+				/*
+				 * Not found or something else bad happened.
+				 */
+				printf ("libfdt %s\n", fdt_strerror(nodeoffset));
+				return 1;
+			}
+		}
+		/*
+		 * Do the delete.  A fourth parameter means delete a property,
+		 * otherwise delete the node.
+		 */
+		if (argc > 3) {
+			err = fdt_delprop(fdt, nodeoffset, argv[3]);
+			if (err < 0) {
+				printf("fdt_delprop libfdt: %s\n", fdt_strerror(err));
+				return err;
+			}
+		} else {
+			err = fdt_del_node(fdt, nodeoffset);
+			if (err < 0) {
+				printf("fdt_del_node libfdt: %s\n", fdt_strerror(err));
+				return err;
+			}
+		}
+
+	/********************************************************************
+	 * Create a chosen node
+	 ********************************************************************/
+	} else if (op == 'c') {
+		fdt_chosen(fdt, 0, 0);
+
+	/********************************************************************
+	 * Create a u-boot-env node
+	 ********************************************************************/
+	} else if (op == 'e') {
+		fdt_env(fdt);
+
+	/********************************************************************
+	 * Create a bd_t node
+	 ********************************************************************/
+	} else if (op == 'b') {
+		fdt_bd_t(fdt);
+
+	/********************************************************************
+	 * Unrecognized command
+	 ********************************************************************/
+	} else {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	return 0;
+}
+
+/********************************************************************/
+
+static int fdt_valid(void)
+{
+	if (fdt == NULL) {
+		printf ("The address of the fdt is invalid.\n");
+		return 0;
+	}
+	if (!fdt || (fdt_magic(fdt) != FDT_MAGIC)) {
+		fdt = NULL;
+		printf ("Unrecognized fdt: bad magic\n");
+		return 0;
+	}
+	if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) {
+		printf ("Unsupported fdt version: $d < %d\n",
+			FDT_FIRST_SUPPORTED_VERSION, fdt_version(fdt));
+		fdt = NULL;
+		return 0;
+	}
+	if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) {
+		printf ("Unsupported fdt version: $d > %d\n",
+			fdt_version(fdt), FDT_LAST_SUPPORTED_VERSION);
+		fdt = NULL;
+		return 0;
+	}
+	return 1;
+}
+
+/********************************************************************/
+
+/*
+ * OF flat tree handling
+ * Written by: Pantelis Antoniou <pantelis.antoniou@gmail.com>
+ * Updated by: Matthew McClintock <msm@freescale.com>
+ * Converted to libfdt by: Gerald Van Baren <vanbaren@cideas.com>
+ */
+
+static int is_printable_string(const void *data, int len)
+{
+	const char *s = data;
+
+	/* zero length is not */
+	if (len == 0)
+		return 0;
+
+	/* must terminate with zero */
+	if (s[len - 1] != '\0')
+		return 0;
+
+	/* printable or a null byte (concatenated strings) */
+	while (((*s == '\0') || isprint(*s)) && (len > 0)) {
+		/*
+		 * If we see a null, there are three possibilities:
+		 * 1) If len == 1, it is the end of the string, printable
+		 * 2) Next character also a null, not printable.
+		 * 3) Next character not a null, continue to check.
+		 */
+		if (s[0] == '\0') {
+			if (len == 1)
+				return 1;
+			if (s[1] == '\0')
+				return 0;
+		}
+		s++;
+		len--;
+	}
+
+	/* Not the null termination, or not done yet: not printable */
+	if (*s != '\0' || (len != 0))
+		return 0;
+
+	return 1;
+}
+
+static void print_data(const void *data, int len)
+{
+	int j;
+	const u8 *s;
+
+	/* no data, don't print */
+	if (len == 0)
+		return;
+
+	/*
+	 * It is a string, but it may have multiple strings (embedded '\0's).
+	 */
+	if (is_printable_string(data, len)) {
+		puts("\"");
+		j = 0;
+		while (j < len) {
+			if (j > 0)
+				puts("\", \"");
+			puts(data);
+			j    += strlen(data) + 1;
+			data += strlen(data) + 1;
+		}
+		puts("\"");
+		return;
+	}
+
+	switch (len) {
+	case 1:	 /* byte */
+		printf("<%02x>", (*(u8 *) data) & 0xff);
+		break;
+	case 2:	 /* half-word */
+		printf("<%04x>", be16_to_cpu(*(u16 *) data) & 0xffff);
+		break;
+	case 4:	 /* word */
+		printf("<%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
+		break;
+	case 8:	 /* double-word */
+#if __WORDSIZE == 64
+		printf("<%016llx>", be64_to_cpu(*(uint64_t *) data));
+#else
+		printf("<%08x ", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
+		data += 4;
+		printf("%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
+#endif
+		break;
+	default:		/* anything else... hexdump */
+		printf("[");
+		for (j = 0, s = data; j < len; j++)
+			printf("%02x%s", s[j], j < len - 1 ? " " : "");
+		printf("]");
+
+		break;
+	}
+}
+
+/********************************************************************/
+
+static int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end)
+{
+	bd_t *bd = gd->bd;
+	int   nodeoffset;
+	int   err;
+	u32   tmp;			/* used to set 32 bit integer properties */
+	char  *str;			/* used to set string properties */
+	ulong clock;
+
+	if (initrd_start && initrd_end) {
+		err = fdt_add_reservemap_entry(fdt,
+			initrd_start, initrd_end - initrd_start + 1);
+		if (err < 0) {
+			printf("libfdt: %s\n", fdt_strerror(err));
+			return err;
+		}
+	}
+
+	/*
+	 * See if we already have a "chosen" node, create it if not.
+	 */
+	nodeoffset = fdt_path_offset (fdt, "/chosen");
+	if (nodeoffset < 0) {
+		/*
+		 * Create a new node "/chosen" (offset 0 is root level)
+		 */
+		nodeoffset = fdt_add_subnode(fdt, 0, "chosen");
+		if (nodeoffset < 0) {
+			printf("libfdt: %s\n", fdt_strerror(nodeoffset));
+			return nodeoffset;
+		}
+	}
+
+	str = getenv("bootargs");
+	if (str != NULL) {
+		err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str)+1);
+		if (err < 0)
+			printf("libfdt: %s\n", fdt_strerror(err));
+	}
+	if (initrd_start && initrd_end) {
+		tmp = __cpu_to_be32(initrd_start);
+		err = fdt_setprop(fdt, nodeoffset, "linux,initrd-start", &tmp, sizeof(tmp));
+		if (err < 0)
+			printf("libfdt: %s\n", fdt_strerror(err));
+		tmp = __cpu_to_be32(initrd_end);
+		err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp));
+		if (err < 0)
+			printf("libfdt: %s\n", fdt_strerror(err));
+	}
+#ifdef OF_STDOUT_PATH
+	err = fdt_setprop(fdt, nodeoffset, "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1);
+	if (err < 0)
+		printf("libfdt: %s\n", fdt_strerror(err));
+#endif
+
+	nodeoffset = fdt_path_offset (fdt, "/cpus");
+	if (nodeoffset >= 0) {
+		clock = cpu_to_be32(bd->bi_intfreq);
+		err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
+		if (err < 0)
+			printf("libfdt: %s\n", fdt_strerror(err));
+	}
+#ifdef OF_TBCLK
+	nodeoffset = fdt_path_offset (fdt, "/cpus/" OF_CPU "/timebase-frequency");
+	if (nodeoffset >= 0) {
+		clock = cpu_to_be32(OF_TBCLK);
+		err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4);
+		if (err < 0)
+			printf("libfdt: %s\n", fdt_strerror(err));
+	}
+#endif
+}
+
+/********************************************************************/
+
+#ifdef CONFIG_OF_HAS_BD_T
+
+/* Function that returns a character from the environment */
+extern uchar(*env_get_char) (int);
+
+#define BDM(x)	{	.name = #x, .offset = offsetof(bd_t, bi_ ##x ) }
+
+static const struct {
+	const char *name;
+	int offset;
+} bd_map[] = {
+	BDM(memstart),
+	BDM(memsize),
+	BDM(flashstart),
+	BDM(flashsize),
+	BDM(flashoffset),
+	BDM(sramstart),
+	BDM(sramsize),
+#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
+	|| defined(CONFIG_E500)
+	BDM(immr_base),
+#endif
+#if defined(CONFIG_MPC5xxx)
+	BDM(mbar_base),
+#endif
+#if defined(CONFIG_MPC83XX)
+	BDM(immrbar),
+#endif
+#if defined(CONFIG_MPC8220)
+	BDM(mbar_base),
+	BDM(inpfreq),
+	BDM(pcifreq),
+	BDM(pevfreq),
+	BDM(flbfreq),
+	BDM(vcofreq),
+#endif
+	BDM(bootflags),
+	BDM(ip_addr),
+	BDM(intfreq),
+	BDM(busfreq),
+#ifdef CONFIG_CPM2
+	BDM(cpmfreq),
+	BDM(brgfreq),
+	BDM(sccfreq),
+	BDM(vco),
+#endif
+#if defined(CONFIG_MPC5xxx)
+	BDM(ipbfreq),
+	BDM(pcifreq),
+#endif
+	BDM(baudrate),
+};
+
+static int fdt_env(void *fdt)
+{
+	int   nodeoffset;
+	int   err;
+	int   k, nxt;
+	int i;
+	static char tmpenv[256];
+
+	/*
+	 * See if we already have a "u-boot-env" node, delete it if so.
+	 * Then create a new empty node.
+	 */
+	nodeoffset = fdt_path_offset (fdt, "/u-boot-env");
+	if (nodeoffset >= 0) {
+		err = fdt_del_node(fdt, nodeoffset);
+		if (err < 0) {
+			printf("libfdt: %s\n", fdt_strerror(err));
+			return err;
+		}
+	}
+	/*
+	 * Create a new node "/u-boot-env" (offset 0 is root level)
+	 */
+	nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env");
+	if (nodeoffset < 0) {
+		printf("libfdt: %s\n", fdt_strerror(nodeoffset));
+		return nodeoffset;
+	}
+
+	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
+		char *s, *lval, *rval;
+
+		/*
+		 * Find the end of the name=definition
+		 */
+		for (nxt = i; env_get_char(nxt) != '\0'; ++nxt)
+			;
+		s = tmpenv;
+		for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k)
+			*s++ = env_get_char(k);
+		*s++ = '\0';
+		lval = tmpenv;
+		/*
+		 * Find the first '=': it separates the name from the value
+		 */
+		s = strchr(tmpenv, '=');
+		if (s != NULL) {
+			*s++ = '\0';
+			rval = s;
+		} else
+			continue;
+		err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1);
+		if (err < 0) {
+			printf("\"%s\" - libfdt: %s\n", lval, fdt_strerror(err));
+			return err;
+		}
+	}
+	return 0;
+}
+#endif /* CONFIG_OF_HAS_UBOOT_ENV */
+
+/********************************************************************/
+
+#ifdef CONFIG_OF_HAS_BD_T
+static int fdt_bd_t(void *fdt)
+{
+	bd_t *bd = gd->bd;
+	int   nodeoffset;
+	int   err;
+	u32   tmp;			/* used to set 32 bit integer properties */
+	int i;
+
+	/*
+	 * See if we already have a "bd_t" node, delete it if so.
+	 * Then create a new empty node.
+	 */
+	nodeoffset = fdt_path_offset (fdt, "/bd_t");
+	if (nodeoffset >= 0) {
+		err = fdt_del_node(fdt, nodeoffset);
+		if (err < 0) {
+			printf("libfdt: %s\n", fdt_strerror(err));
+			return err;
+		}
+	}
+	/*
+	 * Create a new node "/bd_t" (offset 0 is root level)
+	 */
+	nodeoffset = fdt_add_subnode(fdt, 0, "bd_t");
+	if (nodeoffset < 0) {
+		printf("libfdt: %s\n", fdt_strerror(nodeoffset));
+		return nodeoffset;
+	}
+	/*
+	 * Use the string/pointer structure to create the entries...
+	 */
+	for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) {
+		tmp = cpu_to_be32(getenv("bootargs"));
+		err = fdt_setprop(fdt, nodeoffset, bd_map[i].name, &tmp, sizeof(tmp));
+		if (err < 0)
+			printf("libfdt: %s\n", fdt_strerror(err));
+	}
+	/*
+	 * Add a couple of oddball entries...
+	 */
+	err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6);
+	if (err < 0)
+		printf("libfdt: %s\n", fdt_strerror(err));
+	err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4);
+	if (err < 0)
+		printf("libfdt: %s\n", fdt_strerror(err));
+
+#ifdef CONFIG_OF_BOARD_SETUP
+	ft_board_setup(fdt, bd);
+#endif
+
+	return 0;
+}
+#endif /* CONFIG_OF_HAS_BD_T */
+
+/********************************************************************/
+
+U_BOOT_CMD(
+	fdt,	5,	0,	do_fdt,
+	"fdt     - flattened device tree utility commands\n",
+	    "addr   <addr> [<length>]        - Set the fdt location to <addr>\n"
+	"fdt move   <fdt> <newaddr> <length> - Copy the fdt to <addr>\n"
+	"fdt print  <path> [<prop>]          - Recursive print starting at <path>\n"
+	"fdt list   <path> [<prop>]          - Print one level starting at <path>\n"
+	"fdt set    <path> <prop> [<val>]    - Set <property> [to <val>]\n"
+	"fdt mknode <path> <node>            - Create a new node after <path>\n"
+	"fdt rm     <path> [<prop>]          - Delete the node or <property>\n"
+	"fdt chosen - Add/update the \"/chosen\" branch in the tree\n"
+#ifdef CONFIG_OF_HAS_UBOOT_ENV
+	"fdt env    - Add/replace the \"/u-boot-env\" branch in the tree\n"
+#endif
+#ifdef CONFIG_OF_HAS_BD_T
+	"fdt bd_t   - Add/replace the \"/bd_t\" branch in the tree\n"
+#endif
+	"Hints:\n"
+	" * Set a larger length with the fdt addr command to add to the blob.\n"
+	" * If the property you are setting/printing has a '#' character,\n"
+	"     you MUST escape it with a \\ character or quote it with \" or\n"
+	"     it will be ignored as a comment.\n"
+	" * If the value has spaces in it, you MUST escape the spaces with\n"
+	"     \\ characters or quote it with \"\"\n"
+	"Examples: fdt print /               # print the whole tree\n"
+	"          fdt print /cpus \"#address-cells\"\n"
+	"          fdt set   /cpus \"#address-cells\" \"[00 00 00 01]\"\n"
+);
+
+#endif /* CONFIG_OF_FLAT_TREE */
diff --git a/cpu/microblaze/Makefile b/cpu/microblaze/Makefile
index fd54425..db1afa5 100644
--- a/cpu/microblaze/Makefile
+++ b/cpu/microblaze/Makefile
@@ -26,7 +26,8 @@
 LIB	= $(obj)lib$(CPU).a
 
 START	= start.o
-COBJS	= cpu.o interrupts.o
+SOBJS	= dcache.o icache.o irq.o disable_int.o enable_int.o
+COBJS	= cpu.o interrupts.o cache.o exception.o timer.o
 
 SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
diff --git a/cpu/microblaze/cache.c b/cpu/microblaze/cache.c
new file mode 100644
index 0000000..fc388eb
--- /dev/null
+++ b/cpu/microblaze/cache.c
@@ -0,0 +1,48 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal SIMEK <moonstr@monstr.eu>
+ *
+ * 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>
+
+#if (CONFIG_COMMANDS & CFG_CMD_CACHE)
+
+int dcache_status (void)
+{
+	int i = 0;
+	int mask = 0x80;
+	__asm__ __volatile__ ("mfs %0,rmsr"::"r" (i):"memory");
+	/* i&=0x80 */
+	__asm__ __volatile__ ("and %0,%0,%1"::"r" (i), "r" (mask):"memory");
+	return i;
+}
+
+int icache_status (void)
+{
+	int i = 0;
+	int mask = 0x20;
+	__asm__ __volatile__ ("mfs %0,rmsr"::"r" (i):"memory");
+	/* i&=0x20 */
+	__asm__ __volatile__ ("and %0,%0,%1"::"r" (i), "r" (mask):"memory");
+	return i;
+}
+#endif
diff --git a/cpu/microblaze/dcache.S b/cpu/microblaze/dcache.S
new file mode 100644
index 0000000..eaf9671
--- /dev/null
+++ b/cpu/microblaze/dcache.S
@@ -0,0 +1,68 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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
+ */
+	.text
+	.globl	dcache_enable
+	.ent	dcache_enable
+	.align	2
+dcache_enable:
+	/* Make space on stack for a temporary */
+	addi	r1, r1, -4
+	/* Save register r12 */
+	swi	r12, r1, 0
+	/* Read the MSR register */
+	mfs	r12, rmsr
+	/* Set the instruction enable bit */
+	ori	r12, r12, 0x80
+	/* Save the MSR register */
+	mts	rmsr, r12
+	/* Load register r12 */
+	lwi	r12, r1, 0
+	/* Return */
+	rtsd	r15, 8
+	/* Update stack in the delay slot */
+	addi	r1, r1, 4
+	.end	dcache_enable
+
+	.text
+	.globl	dcache_disable
+	.ent	dcache_disable
+	.align	2
+dcache_disable:
+	/* Make space on stack for a temporary */
+	addi	r1, r1, -4
+	/* Save register r12 */
+	swi	r12, r1, 0
+	/* Read the MSR register */
+	mfs	r12, rmsr
+	/* Clear the data cache enable bit */
+	andi	r12, r12, ~0x80
+	/* Save the MSR register */
+	mts	rmsr, r12
+	/* Load register r12 */
+	lwi	r12, r1, 0
+	/* Return */
+	rtsd	r15, 8
+	/* Update stack in the delay slot */
+	addi	r1, r1, 4
+	.end	dcache_disable
diff --git a/cpu/microblaze/disable_int.S b/cpu/microblaze/disable_int.S
new file mode 100644
index 0000000..aecd795
--- /dev/null
+++ b/cpu/microblaze/disable_int.S
@@ -0,0 +1,46 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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
+ */
+
+	.text
+	.globl	microblaze_disable_interrupts
+	.ent	microblaze_disable_interrupts
+	.align	2
+microblaze_disable_interrupts:
+	#Make space on stack for a temporary
+	addi	r1, r1, -4
+	#Save register r12
+	swi	r12, r1, 0
+	#Read the MSR register
+	mfs	r12, rmsr
+	#Clear the interrupt enable bit
+	andi	r12, r12, ~2
+	#Save the MSR register
+	mts	rmsr, r12
+	#Load register r12
+	lwi	r12, r1, 0
+	#Return
+	rtsd	r15, 8
+	#Update stack in the delay slot
+	addi	r1, r1, 4
+	.end	microblaze_disable_interrupts
diff --git a/include/asm-microblaze/platform.h b/cpu/microblaze/enable_int.S
similarity index 63%
rename from include/asm-microblaze/platform.h
rename to cpu/microblaze/enable_int.S
index 2096cce..c096c6c 100644
--- a/include/asm-microblaze/platform.h
+++ b/cpu/microblaze/enable_int.S
@@ -1,7 +1,7 @@
 /*
- * (C) Copyright 2004 Atmark Techno, Inc.
+ * (C) Copyright 2007 Michal Simek
  *
- * Yasushi SHOJI <yashi@atmark-techno.com>
+ * Michal  SIMEK <monstrmonstr.eu>
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -13,7 +13,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
@@ -22,8 +22,17 @@
  * MA 02111-1307 USA
  */
 
-#include <config.h>
-
-#ifdef CONFIG_SUZAKU
-#include <asm/suzaku.h>
-#endif
+	.text
+	.globl	microblaze_enable_interrupts
+	.ent	microblaze_enable_interrupts
+	.align	2
+microblaze_enable_interrupts:
+	addi	r1, r1, -4
+	swi	r12, r1, 0
+	mfs	r12, rmsr
+	ori	r12, r12, 2
+	mts	rmsr, r12
+	lwi	r12, r1, 0
+	rtsd	r15, 8
+	addi	r1, r1, 4
+	.end	microblaze_enable_interrupts
diff --git a/cpu/microblaze/exception.c b/cpu/microblaze/exception.c
new file mode 100644
index 0000000..b135acb
--- /dev/null
+++ b/cpu/microblaze/exception.c
@@ -0,0 +1,68 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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>
+
+void _hw_exception_handler (void)
+{
+	int address = 0;
+	int state = 0;
+	/* loading address of exception EAR */
+	__asm__ __volatile ("mfs %0,rear"::"r" (address):"memory");
+	/* loading excetpion state register ESR */
+	__asm__ __volatile ("mfs %0,resr"::"r" (state):"memory");
+	printf ("Hardware exception at 0x%x address\n", address);
+	switch (state & 0x1f) {	/* mask on exception cause */
+	case 0x1:
+		puts ("Unaligned data access exception\n");
+		break;
+	case 0x2:
+		puts ("Illegal op-code exception\n");
+		break;
+	case 0x3:
+		puts ("Instruction bus error exception\n");
+		break;
+	case 0x4:
+		puts ("Data bus error exception\n");
+		break;
+	case 0x5:
+		puts ("Divide by zero exception\n");
+		break;
+	default:
+		puts ("Undefined cause\n");
+		break;
+	}
+	printf ("Unaligned %sword access\n", ((state & 0x800) ? "" : "half"));
+	printf ("Unaligned %s access\n", ((state & 0x400) ? "store" : "load"));
+	printf ("Register R%x\n", (state & 0x3E) >> 5);
+	hang ();
+}
+
+#ifdef CFG_USR_EXCEP
+void _exception_handler (void)
+{
+	puts ("User vector_exception\n");
+	hang ();
+}
+#endif
diff --git a/cpu/microblaze/icache.S b/cpu/microblaze/icache.S
new file mode 100644
index 0000000..25940d1
--- /dev/null
+++ b/cpu/microblaze/icache.S
@@ -0,0 +1,69 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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
+ */
+
+	.text
+	.globl	icache_enable
+	.ent	icache_enable
+	.align	2
+icache_enable:
+	/* Make space on stack for a temporary */
+	addi	r1, r1, -4
+	/* Save register r12 */
+	swi	r12, r1, 0
+	/* Read the MSR register */
+	mfs	r12, rmsr
+	/* Set the instruction enable bit */
+	ori	r12, r12, 0x20
+	/* Save the MSR register */
+	mts	rmsr, r12
+	/* Load register r12 */
+	lwi	r12, r1, 0
+	/* Return */
+	rtsd	r15, 8
+	/* Update stack in the delay slot */
+	addi	r1, r1, 4
+	.end	icache_enable
+
+	.text
+	.globl	icache_disable
+	.ent	icache_disable
+	.align	2
+icache_disable:
+	/* Make space on stack for a temporary */
+	addi	r1, r1, -4
+	/* Save register r12 */
+	swi	r12, r1, 0
+	/* Read the MSR register */
+	mfs	r12, rmsr
+	/* Clear the instruction enable bit */
+	andi	r12, r12, ~0x20
+	/* Save the MSR register */
+	mts	rmsr, r12
+	/* Load register r12 */
+	lwi	r12, r1, 0
+	/* Return */
+	rtsd	r15, 8
+	/* Update stack in the delay slot */
+	addi	r1, r1, 4
+	.end	icache_disable
diff --git a/cpu/microblaze/interrupts.c b/cpu/microblaze/interrupts.c
index ccf67e1..2db847c 100644
--- a/cpu/microblaze/interrupts.c
+++ b/cpu/microblaze/interrupts.c
@@ -1,6 +1,8 @@
 /*
+ * (C) Copyright 2007 Michal Simek
  * (C) Copyright 2004 Atmark Techno, Inc.
  *
+ * Michal  SIMEK <monstr@monstr.eu>
  * Yasushi SHOJI <yashi@atmark-techno.com>
  *
  * See file CREDITS for list of people who contributed to this
@@ -13,7 +15,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
@@ -22,11 +24,185 @@
  * MA 02111-1307 USA
  */
 
-void enable_interrupts(void)
+#include <common.h>
+#include <command.h>
+#include <asm/microblaze_intc.h>
+
+#undef DEBUG_INT
+
+extern void microblaze_disable_interrupts (void);
+extern void microblaze_enable_interrupts (void);
+
+void enable_interrupts (void)
 {
+	microblaze_enable_interrupts ();
 }
 
-int disable_interrupts(void)
+int disable_interrupts (void)
 {
+	microblaze_disable_interrupts ();
 	return 0;
 }
+
+#ifdef CFG_INTC_0
+#ifdef CFG_TIMER_0
+extern void timer_init (void);
+#endif
+
+static struct irq_action vecs[CFG_INTC_0_NUM];
+
+/* mapping structure to interrupt controller */
+microblaze_intc_t *intc = (microblaze_intc_t *) (CFG_INTC_0_ADDR);
+
+/* default handler */
+void def_hdlr (void)
+{
+	puts ("def_hdlr\n");
+}
+
+void enable_one_interrupt (int irq)
+{
+	int mask;
+	int offset = 1;
+	offset <<= irq;
+	mask = intc->ier;
+	intc->ier = (mask | offset);
+#ifdef DEBUG_INT
+	printf ("Enable one interrupt irq %x - mask %x,ier %x\n", offset, mask,
+		intc->ier);
+	printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+		intc->iar, intc->mer);
+#endif
+}
+
+void disable_one_interrupt (int irq)
+{
+	int mask;
+	int offset = 1;
+	offset <<= irq;
+	mask = intc->ier;
+	intc->ier = (mask & ~offset);
+#ifdef DEBUG_INT
+	printf ("Disable one interrupt irq %x - mask %x,ier %x\n", irq, mask,
+		intc->ier);
+	printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+		intc->iar, intc->mer);
+#endif
+}
+
+/* adding new handler for interrupt */
+void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg)
+{
+	struct irq_action *act;
+	/* irq out of range */
+	if ((irq < 0) || (irq > CFG_INTC_0_NUM)) {
+		puts ("IRQ out of range\n");
+		return;
+	}
+	act = &vecs[irq];
+	if (hdlr) {		/* enable */
+		act->handler = hdlr;
+		act->arg = arg;
+		act->count = 0;
+		enable_one_interrupt (irq);
+	} else {		/* disable */
+
+		act->handler = (interrupt_handler_t *) def_hdlr;
+		act->arg = (void *)irq;
+		disable_one_interrupt (irq);
+	}
+}
+
+/* initialization interrupt controller - hardware */
+void intc_init (void)
+{
+	intc->mer = 0;
+	intc->ier = 0;
+	intc->iar = 0xFFFFFFFF;
+	/* XIntc_Start - hw_interrupt enable and all interrupt enable */
+	intc->mer = 0x3;
+#ifdef DEBUG_INT
+	printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+		intc->iar, intc->mer);
+#endif
+}
+
+int interrupts_init (void)
+{
+	int i;
+	/* initialize irq list */
+	for (i = 0; i < CFG_INTC_0_NUM; i++) {
+		vecs[i].handler = (interrupt_handler_t *) def_hdlr;
+		vecs[i].arg = (void *)i;
+		vecs[i].count = 0;
+	}
+	/* initialize intc controller */
+	intc_init ();
+#ifdef CFG_TIMER_0
+	timer_init ();
+#endif
+	enable_interrupts ();
+	return 0;
+}
+
+void interrupt_handler (void)
+{
+	int irqs;
+	irqs = (intc->isr & intc->ier);	/* find active interrupt */
+
+#ifdef DEBUG_INT
+	printf ("INTC isr %x, ier %x, iar %x, mer %x\n", intc->isr, intc->ier,
+		intc->iar, intc->mer);
+	printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
+#endif
+	struct irq_action *act = vecs;
+	while (irqs) {
+		if (irqs & 1) {
+#ifdef DEBUG_INT
+			printf
+			    ("Jumping to interrupt handler rutine addr %x,count %x,arg %x\n",
+			     act->handler, act->count, act->arg);
+#endif
+			act->handler (act->arg);
+			act->count++;
+		}
+		irqs >>= 1;
+		act++;
+	}
+	intc->iar = 0xFFFFFFFF;	/* erase all events */
+#ifdef DEBUG
+	printf ("Dump INTC reg, isr %x, ier %x, iar %x, mer %x\n", intc->isr,
+		intc->ier, intc->iar, intc->mer);
+	printf ("Interrupt handler on %x line, r14\n", irqs);
+#endif
+}
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_IRQ)
+#ifdef CFG_INTC_0
+int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	int i;
+	struct irq_action *act = vecs;
+
+	puts ("\nInterrupt-Information:\n\n"
+	      "Nr  Routine   Arg       Count\n"
+	      "-----------------------------\n");
+
+	for (i = 0; i < CFG_INTC_0_NUM; i++) {
+		if (act->handler != (interrupt_handler_t*) def_hdlr) {
+			printf ("%02d  %08lx  %08lx  %d\n", i,
+				(int)act->handler, (int)act->arg, act->count);
+		}
+		act++;
+	}
+	puts ("\n");
+	return (0);
+}
+#else
+int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
+{
+	puts ("Undefined interrupt controller\n");
+}
+#endif
+#endif				/* CONFIG_COMMANDS & CFG_CMD_IRQ */
diff --git a/cpu/microblaze/irq.S b/cpu/microblaze/irq.S
new file mode 100644
index 0000000..a4e3fbf
--- /dev/null
+++ b/cpu/microblaze/irq.S
@@ -0,0 +1,165 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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 <config.h>
+	.text
+	.global _interrupt_handler
+_interrupt_handler:
+	addi	r1, r1, -4
+	swi	r2, r1, 0
+	addi	r1, r1, -4
+	swi	r3, r1, 0
+	addi	r1, r1, -4
+	swi	r4, r1, 0
+	addi	r1, r1, -4
+	swi	r5, r1, 0
+	addi	r1, r1, -4
+	swi	r6, r1, 0
+	addi	r1, r1, -4
+	swi	r7, r1, 0
+	addi	r1, r1, -4
+	swi	r8, r1, 0
+	addi	r1, r1, -4
+	swi	r9, r1, 0
+	addi	r1, r1, -4
+	swi	r10, r1, 0
+	addi	r1, r1, -4
+	swi	r11, r1, 0
+	addi	r1, r1, -4
+	swi	r12, r1, 0
+	addi	r1, r1, -4
+	swi	r13, r1, 0
+	addi	r1, r1, -4
+	swi	r14, r1, 0
+	addi	r1, r1, -4
+	swi	r15, r1, 0
+	addi	r1, r1, -4
+	swi	r16, r1, 0
+	addi	r1, r1, -4
+	swi	r17, r1, 0
+	addi	r1, r1, -4
+	swi	r18, r1, 0
+	addi	r1, r1, -4
+	swi	r19, r1, 0
+	addi	r1, r1, -4
+	swi	r20, r1, 0
+	addi	r1, r1, -4
+	swi	r21, r1, 0
+	addi	r1, r1, -4
+	swi	r22, r1, 0
+	addi	r1, r1, -4
+	swi	r23, r1, 0
+	addi	r1, r1, -4
+	swi	r24, r1, 0
+	addi	r1, r1, -4
+	swi	r25, r1, 0
+	addi	r1, r1, -4
+	swi	r26, r1, 0
+	addi	r1, r1, -4
+	swi	r27, r1, 0
+	addi	r1, r1, -4
+	swi	r28, r1, 0
+	addi	r1, r1, -4
+	swi	r29, r1, 0
+	addi	r1, r1, -4
+	swi	r30, r1, 0
+	addi	r1, r1, -4
+	swi	r31, r1, 0
+	brlid	r15, interrupt_handler
+	nop
+	nop
+	lwi	r31, r1, 0
+	addi	r1, r1, 4
+	lwi	r30, r1, 0
+	addi	r1, r1, 4
+	lwi	r29, r1, 0
+	addi	r1, r1, 4
+	lwi	r28, r1, 0
+	addi	r1, r1, 4
+	lwi	r27, r1, 0
+	addi	r1, r1, 4
+	lwi	r26, r1, 0
+	addi	r1, r1, 4
+	lwi	r25, r1, 0
+	addi	r1, r1, 4
+	lwi	r24, r1, 0
+	addi	r1, r1, 4
+	lwi	r23, r1, 0
+	addi	r1, r1, 4
+	lwi	r22, r1, 0
+	addi	r1, r1, 4
+	lwi	r21, r1, 0
+	addi	r1, r1, 4
+	lwi	r20, r1, 0
+	addi	r1, r1, 4
+	lwi	r19, r1, 0
+	addi	r1, r1, 4
+	lwi	r18, r1, 0
+	addi	r1, r1, 4
+	lwi	r17, r1, 0
+	addi	r1, r1, 4
+	lwi	r16, r1, 0
+	addi	r1, r1, 4
+	lwi	r15, r1, 0
+	addi	r1, r1, 4
+	lwi	r14, r1, 0
+	addi	r1, r1, 4
+	lwi	r13, r1, 0
+	addi	r1, r1, 4
+	lwi	r12, r1, 0
+	addi	r1, r1, 4
+	lwi	r11, r1, 0
+	addi	r1, r1, 4
+	lwi	r10, r1, 0
+	addi	r1, r1, 4
+	lwi	r9, r1, 0
+	addi	r1, r1, 4
+	lwi	r8, r1, 0
+	addi	r1, r1, 4
+	lwi	r7, r1, 0
+	addi	r1, r1, 4
+	lwi	r6, r1, 0
+	addi	r1, r1, 4
+	lwi	r5, r1, 0
+	addi	r1, r1, 4
+	lwi	r4, r1, 0
+	addi	r1, r1, 4
+	lwi	r3, r1, 0
+	addi	r1, r1, 4
+	lwi	r2, r1, 0
+	addi	r1, r1, 4
+
+	/* enable_interrupt */
+	addi	r1, r1, -4
+	swi	r12, r1, 0
+	mfs	r12, rmsr
+	ori	r12, r12, 2
+	mts	rmsr, r12
+	lwi	r12, r1, 0
+	addi	r1, r1, 4
+	nop
+	bra	r14
+	nop
+	nop
+	.size _interrupt_handler,.-_interrupt_handler
diff --git a/cpu/microblaze/start.S b/cpu/microblaze/start.S
index 7efdbb0..ca3befc 100644
--- a/cpu/microblaze/start.S
+++ b/cpu/microblaze/start.S
@@ -1,6 +1,8 @@
 /*
+ * (C) Copyright 2007 Michal Simek
  * (C) Copyright 2004 Atmark Techno, Inc.
  *
+ * Michal  SIMEK <monstr@monstr.eu>
  * Yasushi SHOJI <yashi@atmark-techno.com>
  *
  * See file CREDITS for list of people who contributed to this
@@ -13,7 +15,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
@@ -27,10 +29,91 @@
 	.text
 	.global _start
 _start:
+	mts	rmsr, r0	/* disable cache */
+	addi	r1, r0, CFG_INIT_SP_OFFSET
+	addi	r1, r1, -4	/* Decrement SP to top of memory */
+	/* add opcode instruction for 32bit jump - 2 instruction imm & brai*/
+	addi	r6, r0, 0xb000	/* hex b000 opcode imm */
+	bslli	r6, r6, 16	/* shift */
+	swi	r6, r0, 0x0	/* reset address */
+	swi	r6, r0, 0x8	/* user vector exception */
+	swi	r6, r0, 0x10	/* interrupt */
+	swi	r6, r0, 0x20	/* hardware exception */
 
-	addi	r1, r0, CFG_SDRAM_BASE	/* init stack pointer */
-	addi	r1, r1, CFG_SDRAM_SIZE	/* set sp to high up */
+	addi	r6, r0, 0xb808	/* hew b808 opcode brai*/
+	bslli	r6, r6, 16
+	swi	r6, r0, 0x4	/* reset address */
+	swi	r6, r0, 0xC	/* user vector exception */
+	swi	r6, r0, 0x14	/* interrupt */
+	swi	r6, r0, 0x24	/* hardware exception */
 
+#ifdef CFG_RESET_ADDRESS
+	/* reset address */
+	addik	r6, r0, CFG_RESET_ADDRESS
+	sw	r6, r1, r0
+	lhu	r7, r1, r0
+	shi	r7, r0, 0x2
+	shi	r6, r0, 0x6
+/*
+ * Copy U-Boot code to TEXT_BASE
+ * solve problem with sbrk_base
+ */
+#if (CFG_RESET_ADDRESS != TEXT_BASE)
+	addi	r4, r0, __end
+	addi	r5, r0, __text_start
+	rsub	r4, r5, r4	/* size = __end - __text_start */
+	addi	r6, r0, CFG_RESET_ADDRESS	/* source address */
+	addi	r7, r0, 0	/* counter */
+4:
+	lw	r8, r6, r7
+	sw	r8, r5, r7
+	addi	r7, r7, 0x4
+	cmp	r8, r4, r7
+	blti	r8, 4b
+#endif
+#endif
+
+#ifdef CFG_USR_EXCEP
+	/* user_vector_exception */
+	addik	r6, r0, _exception_handler
+	sw	r6, r1, r0
+	lhu	r7, r1, r0
+	shi	r7, r0, 0xa
+	shi	r6, r0, 0xe
+#endif
+
+#ifdef CFG_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
+#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
+
+	/* enable instruction and data cache */
+	mfs	r12, rmsr
+	ori	r12, r12, 0xa0
+	mts	rmsr, r12
+
+clear_bss:
+	/* clear BSS segments */
+	addi	r5, r0, __bss_start
+	addi	r4, r0, __bss_end
+	cmp	r6, r5, r4
+	beqi	r6, 3f
+2:
+	swi     r0, r5, 0 /* write zero to loc */
+	addi    r5, r5, 4 /* increment to next loc */
+	cmp     r6, r5, r4 /* check if we have reach the end */
+	bnei    r6, 2b
+3:	/* jumping to board_init */
 	brai	board_init
-
 1:	bri	1b
diff --git a/cpu/microblaze/timer.c b/cpu/microblaze/timer.c
new file mode 100644
index 0000000..be4fd57
--- /dev/null
+++ b/cpu/microblaze/timer.c
@@ -0,0 +1,68 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.eu>
+ *
+ * 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 <asm/microblaze_timer.h>
+
+volatile int timestamp = 0;
+
+void reset_timer (void)
+{
+	timestamp = 0;
+}
+
+ulong get_timer (ulong base)
+{
+	return (timestamp - base);
+}
+
+void set_timer (ulong t)
+{
+	timestamp = t;
+}
+
+#ifdef CFG_INTC_0
+#ifdef CFG_TIMER_0
+extern void install_interrupt_handler (int irq, interrupt_handler_t * hdlr,
+				       void *arg);
+
+microblaze_timer_t *tmr = (microblaze_timer_t *) (CFG_TIMER_0_ADDR);
+
+void timer_isr (void *arg)
+{
+	timestamp++;
+	tmr->control = tmr->control | TIMER_INTERRUPT;
+}
+
+void timer_init (void)
+{
+	tmr->loadreg = CFG_TIMER_0_PRELOAD;
+	tmr->control = TIMER_INTERRUPT | TIMER_RESET;
+	tmr->control =
+	    TIMER_ENABLE | TIMER_ENABLE_INTR | TIMER_RELOAD | TIMER_DOWN_COUNT;
+	reset_timer ();
+	install_interrupt_handler (CFG_TIMER_0_IRQ, timer_isr, (void *)tmr);
+}
+#endif
+#endif
diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c
index e4bc405..21b1646 100644
--- a/cpu/mpc83xx/cpu.c
+++ b/cpu/mpc83xx/cpu.c
@@ -30,8 +30,14 @@
 #include <watchdog.h>
 #include <command.h>
 #include <mpc83xx.h>
-#include <ft_build.h>
 #include <asm/processor.h>
+#if defined(CONFIG_OF_FLAT_TREE)
+#include <ft_build.h>
+#endif
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -291,6 +297,100 @@
 }
 #endif
 
+#if defined(CONFIG_OF_LIBFDT)
+
+/*
+ * Fixups to the fdt.  If "create" is TRUE, the node is created
+ * unconditionally.  If "create" is FALSE, the node is updated
+ * only if it already exists.
+ */
+#define	FT_UPDATE	0x00000000		/* update existing property only */
+#define	FT_CREATE	0x00000001		/* create property if it doesn't exist */
+#define	FT_BUSFREQ	0x00000002		/* source is bd->bi_busfreq */
+#define	FT_ENETADDR	0x00000004		/* source is bd->bi_enetaddr */
+static const struct {
+	int  createflags;
+	char *node;
+	char *prop;
+} fixup_props[] = {
+	{	FT_CREATE | FT_BUSFREQ,
+		"/cpus/" OF_CPU,
+		 "bus-frequency",
+	},
+	{	FT_CREATE | FT_BUSFREQ,
+		"/cpus/" OF_SOC,
+		"bus-frequency"
+	},
+	{	FT_CREATE | FT_BUSFREQ,
+		"/" OF_SOC "/serial@4500/",
+		"clock-frequency"
+	},
+	{	FT_CREATE | FT_BUSFREQ,
+		"/" OF_SOC "/serial@4600/",
+		"clock-frequency"
+	},
+#ifdef CONFIG_MPC83XX_TSEC1
+	{	FT_UPDATE | FT_ENETADDR,
+		"/" OF_SOC "/ethernet@24000,
+		"mac-address",
+	},
+	{	FT_UPDATE | FT_ENETADDR,
+		"/" OF_SOC "/ethernet@24000,
+		"local-mac-address",
+	},
+#endif
+#ifdef CONFIG_MPC83XX_TSEC2
+	{	FT_UPDATE | FT_ENETADDR,
+		"/" OF_SOC "/ethernet@25000,
+		"mac-address",
+	},
+	{	FT_UPDATE | FT_ENETADDR,
+		"/" OF_SOC "/ethernet@25000,
+		"local-mac-address",
+	},
+#endif
+};
+
+void
+ft_cpu_setup(void *blob, bd_t *bd)
+{
+	int   nodeoffset;
+	int   err;
+	int j;
+
+	for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
+		nodeoffset = fdt_path_offset (fdt, fixup_props[j].node);
+		if (nodeoffset >= 0) {
+			/*
+			 * If unconditional create or the property already exists...
+			 */
+			if ((fixup_props[j].createflags & FT_CREATE) ||
+				(fdt_get_property(fdt, nodeoffset, fixup_props[j].prop, 0))) {
+				if (fixup_props[j].createflags & FT_BUSFREQ) {
+					u32   tmp;
+
+					tmp = cpu_to_be32(bd->bi_busfreq);
+					err = fdt_setprop(fdt, nodeoffset,
+							fixup_props[j].prop, &tmp, sizeof(tmp));
+				} else if (fixup_props[j].createflags & FT_ENETADDR) {
+					err = fdt_setprop(fdt, nodeoffset,
+							fixup_props[j].prop, bd->bi_enetaddr, 6);
+				} else {
+					printf("ft_cpu_setup: %s %s has no flag for the value to set\n",
+						fixup_props[j].node,
+						fixup_props[j].prop);
+				}
+				if (err < 0)
+					printf("libfdt: %s %s returned %s\n",
+						fixup_props[j].node,
+						fixup_props[j].prop,
+						fdt_strerror(err));
+			}
+		}
+	}
+}
+#endif
+
 #if defined(CONFIG_OF_FLAT_TREE)
 void
 ft_cpu_setup(void *blob, bd_t *bd)
diff --git a/include/asm-microblaze/microblaze_intc.h b/include/asm-microblaze/microblaze_intc.h
new file mode 100644
index 0000000..6635aea
--- /dev/null
+++ b/include/asm-microblaze/microblaze_intc.h
@@ -0,0 +1,40 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.cz>
+ *
+ * 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
+ */
+
+typedef volatile struct microblaze_intc_t {
+	int isr; /* interrupt status register */
+	int ipr; /* interrupt pending register */
+	int ier; /* interrupt enable register */
+	int iar; /* interrupt acknowledge register */
+	int sie; /* set interrupt enable bits */
+	int cie; /* clear interrupt enable bits */
+	int ivr; /* interrupt vector register */
+	int mer; /* master enable register */
+} microblaze_intc_t;
+
+struct irq_action {
+	interrupt_handler_t *handler; /* pointer to interrupt rutine */
+	void *arg;
+	int count; /* number of interrupt */
+};
diff --git a/include/asm-microblaze/microblaze_timer.h b/include/asm-microblaze/microblaze_timer.h
new file mode 100644
index 0000000..844c8db
--- /dev/null
+++ b/include/asm-microblaze/microblaze_timer.h
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2007 Michal Simek
+ *
+ * Michal  SIMEK <monstr@monstr.cz>
+ *
+ * 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 TIMER_ENABLE_ALL    0x400 /* ENALL */
+#define TIMER_PWM           0x200 /* PWMA0 */
+#define TIMER_INTERRUPT     0x100 /* T0INT */
+#define TIMER_ENABLE        0x080 /* ENT0 */
+#define TIMER_ENABLE_INTR   0x040 /* ENIT0 */
+#define TIMER_RESET         0x020 /* LOAD0 */
+#define TIMER_RELOAD        0x010 /* ARHT0 */
+#define TIMER_EXT_CAPTURE   0x008 /* CAPT0 */
+#define TIMER_EXT_COMPARE   0x004 /* GENT0 */
+#define TIMER_DOWN_COUNT    0x002 /* UDT0 */
+#define TIMER_CAPTURE_MODE  0x001 /* MDT0 */
+
+typedef volatile struct microblaze_timer_t {
+	int control; /* control/statuc register TCSR */
+	int loadreg; /* load register TLR */
+	int counter; /* timer/counter register */
+} microblaze_timer_t;
diff --git a/include/asm-microblaze/suzaku.h b/include/asm-microblaze/suzaku.h
deleted file mode 100644
index c57a144..0000000
--- a/include/asm-microblaze/suzaku.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * (C) Copyright 2004 Atmark Techno, Inc.
- *
- * Yasushi SHOJI <yashi@atmark-techno.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
- */
-
-/* System Register (GPIO) */
-#define MICROBLAZE_SYSREG_BASE_ADDR 0xFFFFA000
-#define MICROBLAZE_SYSREG_RECONFIGURE (1 << 0)
diff --git a/include/configs/MPC8360EMDS.h b/include/configs/MPC8360EMDS.h
index d2af0e1..79937dc 100644
--- a/include/configs/MPC8360EMDS.h
+++ b/include/configs/MPC8360EMDS.h
@@ -342,8 +342,12 @@
 #endif
 
 /* pass open firmware flat tree */
-#define CONFIG_OF_FLAT_TREE	1
+#define CONFIG_OF_LIBFDT	1
+#undef  CONFIG_OF_FLAT_TREE
 #define CONFIG_OF_BOARD_SETUP	1
+#define CONFIG_OF_HAS_BD_T	1
+#define CONFIG_OF_HAS_UBOOT_ENV	1
+
 
 /* maximum size of the flat tree (8K) */
 #define OF_FLAT_TREE_MAX_SIZE	8192
diff --git a/include/configs/ml401.h b/include/configs/ml401.h
new file mode 100644
index 0000000..cb159e7
--- /dev/null
+++ b/include/configs/ml401.h
@@ -0,0 +1,230 @@
+/*
+ * (C) Copyright 2007 Czech Technical University.
+ *
+ * Michal SIMEK <monstr@seznam.cz>
+ *
+ * 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
+
+#include "../board/xilinx/ml401/xparameters.h"
+
+#define	CONFIG_MICROBLAZE	1	/* MicroBlaze CPU */
+#define	CONFIG_ML401		1	/* ML401 Board */
+
+/* uart */
+#define	CONFIG_SERIAL_BASE	XILINX_UART_BASEADDR
+#define	CONFIG_BAUDRATE		XILINX_UART_BAUDRATE
+#define	CFG_BAUDRATE_TABLE	{ CONFIG_BAUDRATE }
+
+/* setting reset address */
+#define	CFG_RESET_ADDRESS	TEXT_BASE
+
+/* ethernet */
+#define CONFIG_EMACLITE		1
+#define XPAR_EMAC_0_DEVICE_ID	XPAR_XEMAC_NUM_INSTANCES
+
+/* gpio */
+#define	CFG_GPIO_0		1
+#define	CFG_GPIO_0_ADDR		XILINX_GPIO_BASEADDR
+
+/* interrupt controller */
+#define	CFG_INTC_0		1
+#define	CFG_INTC_0_ADDR		XILINX_INTC_BASEADDR
+#define	CFG_INTC_0_NUM		XILINX_INTC_NUM_INTR_INPUTS
+
+/* timer */
+#define	CFG_TIMER_0		1
+#define	CFG_TIMER_0_ADDR	XILINX_TIMER_BASEADDR
+#define	CFG_TIMER_0_IRQ		XILINX_TIMER_IRQ
+#define	FREQUENCE		XILINX_CLOCK_FREQ
+#define	CFG_TIMER_0_PRELOAD	( FREQUENCE/1000 )
+
+/*
+ * memory layout - Example
+ * TEXT_BASE = 0x1200_0000;
+ * CFG_SRAM_BASE = 0x1000_0000;
+ * CFG_SRAM_SIZE = 0x0400_0000;
+ *
+ * CFG_GBL_DATA_OFFSET = 0x1000_0000 + 0x0400_0000 - 0x1000 = 0x13FF_F000
+ * CFG_MONITOR_BASE = 0x13FF_F000 - 0x40000 = 0x13FB_F000
+ * CFG_MALLOC_BASE = 0x13FB_F000 - 0x40000 = 0x13F7_F000
+ *
+ * 0x1000_0000	CFG_SDRAM_BASE
+ *					FREE
+ * 0x1200_0000	TEXT_BASE
+ *		U-BOOT code
+ * 0x1202_0000
+ *					FREE
+ *
+ *					STACK
+ * 0x13F7_F000	CFG_MALLOC_BASE
+ *					MALLOC_AREA	256kB	Alloc
+ * 0x11FB_F000	CFG_MONITOR_BASE
+ *					MONITOR_CODE	256kB	Env
+ * 0x13FF_F000	CFG_GBL_DATA_OFFSET
+ * 					GLOBAL_DATA	4kB	bd, gd
+ * 0x1400_0000	CFG_SDRAM_BASE + CFG_SDRAM_SIZE
+ */
+
+/* ddr sdram - main memory */
+#define	CFG_SDRAM_BASE		XILINX_RAM_START
+#define	CFG_SDRAM_SIZE		XILINX_RAM_SIZE
+#define	CFG_MEMTEST_START	CFG_SDRAM_BASE
+#define	CFG_MEMTEST_END		(CFG_SDRAM_BASE + 0x1000)
+
+/* global pointer */
+#define	CFG_GBL_DATA_SIZE	0x1000	/* size of global data */
+#define	CFG_GBL_DATA_OFFSET     (CFG_SDRAM_BASE + CFG_SDRAM_SIZE - CFG_GBL_DATA_SIZE) /* start of global data */
+
+/* monitor code */
+#define	SIZE			0x40000
+#define	CFG_MONITOR_LEN		SIZE
+#define	CFG_MONITOR_BASE	(CFG_GBL_DATA_OFFSET - CFG_MONITOR_LEN)
+#define	CFG_MONITOR_END		(CFG_MONITOR_BASE + CFG_MONITOR_LEN)
+#define	CFG_MALLOC_LEN		SIZE
+#define	CFG_MALLOC_BASE		(CFG_MONITOR_BASE - CFG_MALLOC_LEN)
+
+/* stack */
+#define	CFG_INIT_SP_OFFSET	CFG_MONITOR_BASE
+
+/*#define	RAMENV */
+#define	FLASH
+
+#ifdef FLASH
+	#define	CFG_FLASH_BASE		XILINX_FLASH_START
+	#define	CFG_FLASH_SIZE		XILINX_FLASH_SIZE
+	#define	CFG_FLASH_CFI		1
+	#define	CFG_FLASH_CFI_DRIVER	1
+	#define	CFG_FLASH_EMPTY_INFO	1	/* ?empty sector */
+	#define	CFG_MAX_FLASH_BANKS	1	/* max number of memory banks */
+	#define	CFG_MAX_FLASH_SECT	128	/* max number of sectors on one chip */
+
+	#ifdef	RAMENV
+		#define	CFG_ENV_IS_NOWHERE	1
+		#define	CFG_ENV_SIZE		0x1000
+		#define	CFG_ENV_ADDR		(CFG_MONITOR_BASE - CFG_ENV_SIZE)
+
+	#else	/* !RAMENV */
+		#define	CFG_ENV_IS_IN_FLASH	1
+		#define	CFG_ENV_ADDR		0x40000
+		#define	CFG_ENV_SECT_SIZE	0x40000	/* 256K(one sector) for env */
+		#define	CFG_ENV_SIZE		0x2000
+	#endif /* !RAMBOOT */
+#else /* !FLASH */
+	/* ENV in RAM */
+	#define	CFG_NO_FLASH		1
+	#define	CFG_ENV_IS_NOWHERE	1
+	#define	CFG_ENV_SIZE		0x1000
+	#define	CFG_ENV_ADDR		(CFG_MONITOR_BASE - CFG_ENV_SIZE)
+#endif /* !FLASH */
+
+#ifdef	FLASH
+	#ifdef	RAMENV
+	#define	CONFIG_COMMANDS	(CONFIG__CMD_DFL |\
+				CFG_CMD_MEMORY |\
+				CFG_CMD_MISC |\
+				CFG_CMD_AUTOSCRIPT |\
+				CFG_CMD_IRQ |\
+				CFG_CMD_ASKENV |\
+				CFG_CMD_BDI |\
+				CFG_CMD_RUN |\
+				CFG_CMD_LOADS |\
+				CFG_CMD_LOADB |\
+				CFG_CMD_IMI |\
+				CFG_CMD_NET |\
+				CFG_CMD_CACHE |\
+				CFG_CMD_IMLS |\
+				CFG_CMD_FLASH |\
+				CFG_CMD_PING \
+				)
+	#else	/* !RAMENV */
+	#define	CONFIG_COMMANDS	(CONFIG__CMD_DFL |\
+				CFG_CMD_MEMORY |\
+				CFG_CMD_MISC |\
+				CFG_CMD_AUTOSCRIPT |\
+				CFG_CMD_IRQ |\
+				CFG_CMD_ASKENV |\
+				CFG_CMD_BDI |\
+				CFG_CMD_RUN |\
+				CFG_CMD_LOADS |\
+				CFG_CMD_LOADB |\
+				CFG_CMD_IMI |\
+				CFG_CMD_NET |\
+				CFG_CMD_CACHE |\
+				CFG_CMD_IMLS |\
+				CFG_CMD_FLASH |\
+				CFG_CMD_PING |\
+				CFG_CMD_ENV |\
+				CFG_CMD_SAVES \
+				)
+
+	#endif
+
+#else	/* !FLASH */
+	#define	CONFIG_COMMANDS	(CONFIG__CMD_DFL |\
+				CFG_CMD_MEMORY |\
+				CFG_CMD_MISC |\
+				CFG_CMD_AUTOSCRIPT |\
+				CFG_CMD_IRQ |\
+				CFG_CMD_ASKENV |\
+				CFG_CMD_BDI |\
+				CFG_CMD_RUN |\
+				CFG_CMD_LOADS |\
+				CFG_CMD_LOADB |\
+				CFG_CMD_IMI |\
+				CFG_CMD_NET |\
+				CFG_CMD_CACHE |\
+				CFG_CMD_PING \
+				)
+#endif	/* !FLASH */
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/* Miscellaneous configurable options */
+#define	CFG_PROMPT	"U-Boot-mONStR> "
+#define	CFG_CBSIZE	512	/* size of console buffer */
+#define	CFG_PBSIZE	(CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) /* print buffer size */
+#define	CFG_MAXARGS	15	/* max number of command args */
+#define	CFG_LONGHELP
+#define	CFG_LOAD_ADDR	0x12000000 /* default load address */
+
+#define	CONFIG_BOOTDELAY 	30
+#define	CONFIG_BOOTARGS		"root=romfs"
+#define	CONFIG_HOSTNAME		"ml401"
+#define	CONFIG_BOOTCOMMAND 	"base 0;tftp 11000000 image.img;bootm"
+#define	CONFIG_IPADDR		192.168.0.3
+#define	CONFIG_SERVERIP 	192.168.0.5
+#define	CONFIG_GATEWAYIP 	192.168.0.1
+#define	CONFIG_ETHADDR		00:E0:0C:00:00:FD
+
+/* architecture dependent code */
+#define	CFG_USR_EXCEP	/* user exception */
+#define CFG_HZ	1000
+
+/* system ace */
+/*#define CONFIG_SYSTEMACE
+#define DEBUG_SYSTEMACE
+#define CFG_SYSTEMACE_BASE	XILINX_SYSACE_BASEADDR
+#define CFG_SYSTEMACE_WIDTH	XILINX_SYSACE_MEM_WIDTH
+#define CONFIG_DOS_PARTITION
+*/
+#endif	/* __CONFIG_H */
diff --git a/include/configs/suzaku.h b/include/configs/suzaku.h
index 1ee6be1..8224555 100644
--- a/include/configs/suzaku.h
+++ b/include/configs/suzaku.h
@@ -44,12 +44,17 @@
 #define CFG_FLASH_SIZE		0x00400000
 #define CFG_RESET_ADDRESS	0xfff00100
 #define CFG_MONITOR_LEN		(256 << 10)	/* Reserve 256 kB for Monitor */
-#define CFG_MONITOR_BASE        (CFG_SDRAM_BASE + CFG_SDRAM_SIZE - (1024 * 1024))
+#define CFG_MONITOR_BASE	(CFG_SDRAM_BASE + CFG_SDRAM_SIZE - (1024 * 1024))
 #define CFG_MALLOC_LEN		(256 << 10)	/* Reserve 256 kB for malloc */
+#define CFG_MALLOC_BASE		(CFG_MONITOR_BASE - (1024 * 1024))
 
 #define CONFIG_BAUDRATE		115200
 #define CFG_BAUDRATE_TABLE	{ 115200 }
 
+/* System Register (GPIO) */
+#define MICROBLAZE_SYSREG_BASE_ADDR 0xFFFFA000
+#define MICROBLAZE_SYSREG_RECONFIGURE (1 << 0)
+
 #define CONFIG_COMMANDS		(CONFIG__CMD_DFL)
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
diff --git a/include/configs/xupv2p.h b/include/configs/xupv2p.h
new file mode 100644
index 0000000..a2f4810
--- /dev/null
+++ b/include/configs/xupv2p.h
@@ -0,0 +1,174 @@
+/*
+ * (C) Copyright 2007 Czech Technical University.
+ *
+ * Michal SIMEK <monstr@monstr.eu>
+ *
+ * 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
+
+#include "../board/xilinx/xupv2p/xparameters.h"
+
+#define	CONFIG_MICROBLAZE	1	/* MicroBlaze CPU */
+#define	CONFIG_XUPV2P		1
+
+/* uart */
+#define	CONFIG_SERIAL_BASE	XILINX_UART_BASEADDR
+#define	CONFIG_BAUDRATE		XILINX_UART_BAUDRATE
+#define	CFG_BAUDRATE_TABLE	{ CONFIG_BAUDRATE }
+
+/* ethernet */
+#define CONFIG_EMAC	1
+#define XPAR_EMAC_0_DEVICE_ID	XPAR_XEMAC_NUM_INSTANCES
+
+/*
+ * setting reset address
+ *
+ * TEXT_BASE is set to place, where the U-BOOT run in RAM, but
+ * if you want to store U-BOOT in flash, set CFG_RESET_ADDRESS
+ * to FLASH memory and after loading bitstream jump to FLASH.
+ * U-BOOT auto-relocate to TEXT_BASE. After RESET command Microblaze
+ * jump to CFG_RESET_ADDRESS where is the original U-BOOT code.
+ */
+#define	CFG_RESET_ADDRESS	0x36000000
+
+/* gpio */
+#define	CFG_GPIO_0		1
+#define	CFG_GPIO_0_ADDR		XILINX_GPIO_BASEADDR
+
+/* interrupt controller */
+#define	CFG_INTC_0		1
+#define	CFG_INTC_0_ADDR		XILINX_INTC_BASEADDR
+#define	CFG_INTC_0_NUM		XILINX_INTC_NUM_INTR_INPUTS
+
+/* timer */
+#define	CFG_TIMER_0		1
+#define	CFG_TIMER_0_ADDR	XILINX_TIMER_BASEADDR
+#define	CFG_TIMER_0_IRQ		XILINX_TIMER_IRQ
+#define	FREQUENCE		XILINX_CLOCK_FREQ
+#define	CFG_TIMER_0_PRELOAD	( FREQUENCE/1000 )
+
+/*
+ * memory layout - Example
+ * TEXT_BASE = 0x3600_0000;
+ * CFG_SRAM_BASE = 0x3000_0000;
+ * CFG_SRAM_SIZE = 0x1000_0000;
+ *
+ * CFG_GBL_DATA_OFFSET = 0x3000_0000 + 0x1000_0000 - 0x1000 = 0x3FFF_F000
+ * CFG_MONITOR_BASE = 0x3FFF_F000 - 0x40000 = 0x3FFB_F000
+ * CFG_MALLOC_BASE = 0x3FFB_F000 - 0x40000 = 0x3FF7_F000
+ *
+ * 0x3000_0000	CFG_SDRAM_BASE
+ *					FREE
+ * 0x3600_0000	TEXT_BASE
+ *		U-BOOT code
+ * 0x3602_0000
+ *					FREE
+ *
+ *					STACK
+ * 0x3FF7_F000	CFG_MALLOC_BASE
+ *					MALLOC_AREA	256kB	Alloc
+ * 0x3FFB_F000	CFG_MONITOR_BASE
+ *					MONITOR_CODE	256kB	Env
+ * 0x3FFF_F000	CFG_GBL_DATA_OFFSET
+ * 					GLOBAL_DATA	4kB	bd, gd
+ * 0x4000_0000	CFG_SDRAM_BASE + CFG_SDRAM_SIZE
+ */
+
+/* ddr sdram - main memory */
+#define	CFG_SDRAM_BASE		XILINX_RAM_START
+#define	CFG_SDRAM_SIZE		XILINX_RAM_SIZE
+#define	CFG_MEMTEST_START	CFG_SDRAM_BASE
+#define	CFG_MEMTEST_END		(CFG_SDRAM_BASE + 0x1000)
+
+/* global pointer */
+#define	CFG_GBL_DATA_SIZE	0x1000	/* size of global data */
+#define	CFG_GBL_DATA_OFFSET     (CFG_SDRAM_BASE + CFG_SDRAM_SIZE - CFG_GBL_DATA_SIZE) /* start of global data */
+
+/* monitor code */
+#define	SIZE			0x40000
+#define	CFG_MONITOR_LEN		SIZE
+#define	CFG_MONITOR_BASE	(CFG_GBL_DATA_OFFSET - CFG_MONITOR_LEN)
+#define	CFG_MONITOR_END		(CFG_MONITOR_BASE + CFG_MONITOR_LEN)
+#define	CFG_MALLOC_LEN		SIZE
+#define	CFG_MALLOC_BASE		(CFG_MONITOR_BASE - CFG_MALLOC_LEN)
+
+/* stack */
+#define	CFG_INIT_SP_OFFSET	CFG_MALLOC_BASE
+
+#define	CFG_NO_FLASH		1
+#define	CFG_ENV_IS_NOWHERE	1
+#define	CFG_ENV_SIZE		0x1000
+#define	CFG_ENV_ADDR		(CFG_MONITOR_BASE - CFG_ENV_SIZE)
+#define	CONFIG_COMMANDS	(CONFIG__CMD_DFL |\
+			CFG_CMD_MEMORY |\
+			CFG_CMD_IRQ |\
+			CFG_CMD_BDI |\
+			CFG_CMD_NET |\
+			CFG_CMD_IMI |\
+			CFG_CMD_ECHO |\
+			CFG_CMD_CACHE |\
+			CFG_CMD_RUN |\
+			CFG_CMD_AUTOSCRIPT |\
+			CFG_CMD_ASKENV |\
+			CFG_CMD_LOADS |\
+			CFG_CMD_LOADB |\
+			CFG_CMD_MISC |\
+			CFG_CMD_PING \
+			)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/* Miscellaneous configurable options */
+#define	CFG_PROMPT	"U-Boot-mONStR> "
+#define	CFG_CBSIZE	512	/* size of console buffer */
+#define	CFG_PBSIZE	(CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) /* print buffer size */
+#define	CFG_MAXARGS	15	/* max number of command args */
+#define	CFG_LONGHELP
+#define	CFG_LOAD_ADDR	0x12000000 /* default load address */
+
+#define	CONFIG_BOOTDELAY 	30
+#define	CONFIG_BOOTARGS		"root=romfs"
+#define	CONFIG_HOSTNAME		"ml401"
+#define	CONFIG_BOOTCOMMAND 	"base 0;tftp 11000000 image.img;bootm"
+#define	CONFIG_IPADDR		192.168.0.3
+#define	CONFIG_SERVERIP 	192.168.0.5
+#define	CONFIG_GATEWAYIP 	192.168.0.1
+#define	CONFIG_ETHADDR		00:E0:0C:00:00:FD
+
+/* architecture dependent code */
+#define	CFG_USR_EXCEP	/* user exception */
+#define CFG_HZ	1000
+
+#define CONFIG_PREBOOT	"echo U-BOOT by mONStR;"	\
+	"base 0;" \
+	"echo"
+
+
+/* system ace */
+/*#define	CONFIG_SYSTEMACE
+#define	DEBUG_SYSTEMACE
+#define	CFG_SYSTEMACE_BASE	0xCF000000
+#define	CFG_SYSTEMACE_WIDTH	16
+#define	CONFIG_DOS_PARTITION*/
+
+#endif	/* __CONFIG_H */
diff --git a/include/fdt.h b/include/fdt.h
new file mode 100644
index 0000000..48ccfd9
--- /dev/null
+++ b/include/fdt.h
@@ -0,0 +1,60 @@
+#ifndef _FDT_H
+#define _FDT_H
+
+#ifndef __ASSEMBLY__
+
+struct fdt_header {
+	uint32_t magic;			 /* magic word FDT_MAGIC */
+	uint32_t totalsize;		 /* total size of DT block */
+	uint32_t off_dt_struct;		 /* offset to structure */
+	uint32_t off_dt_strings;	 /* offset to strings */
+	uint32_t off_mem_rsvmap;	 /* offset to memory reserve map */
+	uint32_t version;		 /* format version */
+	uint32_t last_comp_version;	 /* last compatible version */
+
+	/* version 2 fields below */
+	uint32_t boot_cpuid_phys;	 /* Which physical CPU id we're
+					    booting on */
+	/* version 3 fields below */
+	uint32_t size_dt_strings;	 /* size of the strings block */
+
+	/* version 17 fields below */
+	uint32_t size_dt_struct;	 /* size of the structure block */
+};
+
+struct fdt_reserve_entry {
+	uint64_t address;
+	uint64_t size;
+};
+
+struct fdt_node_header {
+	uint32_t tag;
+	char name[0];
+};
+
+struct fdt_property {
+	uint32_t tag;
+	uint32_t len;
+	uint32_t nameoff;
+	char data[0];
+};
+
+#endif /* !__ASSEMBLY */
+
+#define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
+#define FDT_TAGSIZE	sizeof(uint32_t)
+
+#define FDT_BEGIN_NODE	0x1		/* Start node: full name */
+#define FDT_END_NODE	0x2		/* End node */
+#define FDT_PROP	0x3		/* Property: name off,
+					   size, content */
+#define FDT_NOP		0x4		/* nop */
+#define FDT_END		0x9
+
+#define FDT_V1_SIZE	(7*sizeof(uint32_t))
+#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(uint32_t))
+#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V16_SIZE	FDT_V3_SIZE
+#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(uint32_t))
+
+#endif /* _FDT_H */
diff --git a/include/libfdt.h b/include/libfdt.h
new file mode 100644
index 0000000..a0b4d55
--- /dev/null
+++ b/include/libfdt.h
@@ -0,0 +1,138 @@
+#ifndef _LIBFDT_H
+#define _LIBFDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <fdt.h>
+#include <libfdt_env.h>
+
+#define FDT_FIRST_SUPPORTED_VERSION	0x10
+#define FDT_LAST_SUPPORTED_VERSION	0x11
+
+/* Error codes: informative error codes */
+#define FDT_ERR_NOTFOUND	1
+#define FDT_ERR_EXISTS		2
+#define FDT_ERR_NOSPACE		3
+
+/* Error codes: codes for bad parameters */
+#define FDT_ERR_BADOFFSET	4
+#define FDT_ERR_BADPATH		5
+#define FDT_ERR_BADSTATE	6
+
+/* Error codes: codes for bad device tree blobs */
+#define FDT_ERR_TRUNCATED	7
+#define FDT_ERR_BADMAGIC	8
+#define FDT_ERR_BADVERSION	9
+#define FDT_ERR_BADSTRUCTURE	10
+#define FDT_ERR_BADLAYOUT	11
+
+#define FDT_ERR_MAX		11
+
+#define fdt_get_header(fdt, field) \
+	(fdt32_to_cpu(((struct fdt_header *)(fdt))->field))
+#define fdt_magic(fdt)			(fdt_get_header(fdt, magic))
+#define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
+#define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
+#define fdt_off_dt_strings(fdt)		(fdt_get_header(fdt, off_dt_strings))
+#define fdt_off_mem_rsvmap(fdt)		(fdt_get_header(fdt, off_mem_rsvmap))
+#define fdt_version(fdt)		(fdt_get_header(fdt, version))
+#define fdt_last_comp_version(fdt)	(fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt)	(fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt)	(fdt_get_header(fdt, size_dt_strings))
+#define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct))
+
+#define fdt_set_header(fdt, field, val) \
+	((struct fdt_header *)(fdt))->field = cpu_to_fdt32(val)
+
+void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+
+#define fdt_offset_ptr_typed(fdt, offset, var) \
+	((typeof(var))(fdt_offset_ptr((fdt), (offset), sizeof(*(var)))))
+
+int fdt_move(const void *fdt, void *buf, int bufsize);
+
+/* Read-only functions */
+char *fdt_string(const void *fdt, int stroffset);
+
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+			       const char *name, int namelen);
+int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
+
+int fdt_path_offset(const void *fdt, const char *path);
+
+struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
+				      const char *name, int *lenp);
+void *fdt_getprop(const void *fdt, int nodeoffset,
+		  const char *name, int *lenp);
+
+uint32_t fdt_next_tag(const void *fdt, int offset,
+		      int *nextoffset, char **namep);
+
+/* Write-in-place functions */
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+			const void *val, int len);
+
+#define fdt_setprop_inplace_typed(fdt, nodeoffset, name, val) \
+	({ \
+		typeof(val) x = val; \
+		fdt_setprop_inplace(fdt, nodeoffset, name, &x, sizeof(x)); \
+	})
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
+int fdt_nop_node(void *fdt, int nodeoffset);
+
+/* Sequential-write functions */
+int fdt_create(void *buf, int bufsize);
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
+int fdt_finish_reservemap(void *fdt);
+int fdt_begin_node(void *fdt, const char *name);
+int fdt_property(void *fdt, const char *name, const void *val, int len);
+#define fdt_property_typed(fdt, name, val) \
+	({ \
+		typeof(val) x = (val); \
+		fdt_property((fdt), (name), &x, sizeof(x)); \
+	})
+#define fdt_property_string(fdt, name, str) \
+	fdt_property(fdt, name, str, strlen(str)+1)
+int fdt_end_node(void *fdt);
+int fdt_finish(void *fdt);
+
+/* Read-write functions */
+int fdt_open_into(void *fdt, void *buf, int bufsize);
+int fdt_pack(void *fdt);
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len);
+#define fdt_setprop_typed(fdt, nodeoffset, name, val) \
+	({ \
+		typeof(val) x = (val); \
+		fdt_setprop((fdt), (nodeoffset), (name), &x, sizeof(x)); \
+	})
+#define fdt_setprop_string(fdt, nodeoffset, name, str) \
+	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+			    const char *name, int namelen);
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
+int fdt_del_node(void *fdt, int nodeoffset);
+
+/* Extra functions */
+const char *fdt_strerror(int errval);
+
+#endif /* _LIBFDT_H */
diff --git a/include/libfdt_env.h b/include/libfdt_env.h
new file mode 100644
index 0000000..6c77852
--- /dev/null
+++ b/include/libfdt_env.h
@@ -0,0 +1,16 @@
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <stddef.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <linux/string.h>
+
+struct fdt_header *fdt;         /* Pointer to the working fdt */
+
+#define fdt32_to_cpu(x)		__be32_to_cpu(x)
+#define cpu_to_fdt32(x)		__cpu_to_be32(x)
+#define fdt64_to_cpu(x)		__be64_to_cpu(x)
+#define cpu_to_fdt64(x)		__cpu_to_be64(x)
+
+#endif /* _LIBFDT_ENV_H */
diff --git a/lib_microblaze/board.c b/lib_microblaze/board.c
index 026d247..c95125a 100644
--- a/lib_microblaze/board.c
+++ b/lib_microblaze/board.c
@@ -1,6 +1,8 @@
 /*
+ * (C) Copyright 2007 Michal Simek
  * (C) Copyright 2004 Atmark Techno, Inc.
  *
+ * Michal  SIMEK <monstr@monstr.eu>
  * Yasushi SHOJI <yashi@atmark-techno.com>
  *
  * See file CREDITS for list of people who contributed to this
@@ -13,7 +15,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
@@ -30,8 +32,18 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-const char version_string[] =
-	U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")";
+const char version_string[] = U_BOOT_VERSION " (" __DATE__ " - " __TIME__ ")";
+
+#ifdef CFG_GPIO_0
+extern int gpio_init (void);
+#endif
+#ifdef CFG_INTC_0
+extern int interrupts_init (void);
+#endif
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+extern int eth_init (bd_t * bis);
+extern int getenv_IPaddr (char *);
+#endif
 
 /*
  * Begin and End of memory area for malloc(), and current "brk"
@@ -40,6 +52,18 @@
 static ulong mem_malloc_end;
 static ulong mem_malloc_brk;
 
+/*
+ * The Malloc area is immediately below the monitor copy in DRAM
+ * aka CFG_MONITOR_BASE - Note there is no need for reloc_off
+ * as our monitory code is run from SDRAM
+ */
+static void mem_malloc_init (void)
+{
+	mem_malloc_end = (CFG_MALLOC_BASE + CFG_MALLOC_LEN);
+	mem_malloc_start = CFG_MALLOC_BASE;
+	mem_malloc_brk = mem_malloc_start;
+	memset ((void *)mem_malloc_start, 0, mem_malloc_end - mem_malloc_start);
+}
 
 void *sbrk (ptrdiff_t increment)
 {
@@ -50,7 +74,7 @@
 		return (NULL);
 	}
 	mem_malloc_brk = new;
-	return ((void *) old);
+	return ((void *)old);
 }
 
 /*
@@ -68,24 +92,36 @@
 typedef int (init_fnc_t) (void);
 
 init_fnc_t *init_sequence[] = {
-	serial_init,		/* serial communications setup */
+	env_init,
+	serial_init,
+#ifdef CFG_GPIO_0
+	gpio_init,
+#endif
+#ifdef CFG_INTC_0
+	interrupts_init,
+#endif
 	NULL,
 };
 
-void board_init(void)
+void board_init (void)
 {
 	bd_t *bd;
 	init_fnc_t **init_fnc_ptr;
-
-	/* Pointer is writable since we allocated a register for it. */
-	gd = (gd_t *)CFG_GBL_DATA_OFFSET;
-	memset((void *)gd, 0, CFG_GBL_DATA_SIZE);
-
-	gd->bd = (bd_t *)(gd+1);	/* At end of global data */
+	gd = (gd_t *) CFG_GBL_DATA_OFFSET;
+#if (CONFIG_COMMANDS & CFG_CMD_FLASH)
+	ulong flash_size = 0;
+#endif
+	asm ("nop");	/* FIXME gd is not initialize - wait */
+	memset ((void *)gd, 0, CFG_GBL_DATA_SIZE);
+	gd->bd = (bd_t *) (gd + 1);	/* At end of global data */
 	gd->baudrate = CONFIG_BAUDRATE;
-
 	bd = gd->bd;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
+	bd->bi_memstart = CFG_SDRAM_BASE;
+	bd->bi_memsize = CFG_SDRAM_SIZE;
+
+	/* Initialise malloc() area */
+	mem_malloc_init ();
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
 		WATCHDOG_RESET ();
@@ -94,6 +130,37 @@
 		}
 	}
 
+#if (CONFIG_COMMANDS & CFG_CMD_FLASH)
+	bd->bi_flashstart = CFG_FLASH_BASE;
+	if (0 < (flash_size = flash_init ())) {
+		bd->bi_flashsize = flash_size;
+		bd->bi_flashoffset = CFG_FLASH_BASE + flash_size;
+	} else {
+		puts ("Flash init FAILED");
+		bd->bi_flashstart = 0;
+		bd->bi_flashsize = 0;
+		bd->bi_flashoffset = 0;
+	}
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET)
+	char *s, *e;
+	int i;
+	/* board MAC address */
+	s = getenv ("ethaddr");
+	for (i = 0; i < 6; ++i) {
+		bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
+		if (s)
+			s = (*e) ? e + 1 : e;
+	}
+	/* IP Address */
+	bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
+	eth_init (bd);
+#endif
+
+	/* relocate environment function pointers etc. */
+	env_relocate ();
+
 	/* main_loop */
 	for (;;) {
 		WATCHDOG_RESET ();
@@ -104,5 +171,5 @@
 void hang (void)
 {
 	puts ("### ERROR ### Please RESET the board ###\n");
-	for (;;);
+	for (;;) ;
 }
diff --git a/lib_microblaze/microblaze_linux.c b/lib_microblaze/microblaze_linux.c
index b3a0815..2c7885c 100644
--- a/lib_microblaze/microblaze_linux.c
+++ b/lib_microblaze/microblaze_linux.c
@@ -1,6 +1,8 @@
 /*
+ * (C) Copyright 2007 Michal Simek
  * (C) Copyright 2004 Atmark Techno, Inc.
  *
+ * Michal  SIMEK <monstr@monstr.eu>
  * Yasushi SHOJI <yashi@atmark-techno.com>
  *
  * See file CREDITS for list of people who contributed to this
@@ -13,7 +15,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
@@ -24,8 +26,146 @@
 
 #include <common.h>
 #include <command.h>
+#include <image.h>
+#include <zlib.h>
+#include <asm/byteorder.h>
 
-void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
-		ulong addr, ulong *len_ptr, int   verify)
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SHOW_BOOT_PROGRESS
+# include <status_led.h>
+# define SHOW_BOOT_PROGRESS(arg)        show_boot_progress(arg)
+#else
+# define SHOW_BOOT_PROGRESS(arg)
+#endif
+
+extern image_header_t header;	/* from cmd_bootm.c */
+/*cmd_boot.c*/
+extern int do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
+
+void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
+		     ulong addr, ulong * len_ptr, int verify)
 {
+	ulong len = 0, checksum;
+	ulong initrd_start, initrd_end;
+	ulong data;
+	/* First parameter is mapped to $r5 for kernel boot args */
+	void (*theKernel) (char *);
+	image_header_t *hdr = &header;
+	char *commandline = getenv ("bootargs");
+	int i;
+
+	theKernel = (void (*)(char *))ntohl (hdr->ih_ep);
+
+	/* Check if there is an initrd image */
+	if (argc >= 3) {
+		SHOW_BOOT_PROGRESS (9);
+
+		addr = simple_strtoul (argv[2], NULL, 16);
+
+		printf ("## Loading Ramdisk Image at %08lx ...\n", addr);
+
+		/* Copy header so we can blank CRC field for re-calculation */
+		memcpy (&header, (char *)addr, sizeof (image_header_t));
+
+		if (ntohl (hdr->ih_magic) != IH_MAGIC) {
+			printf ("Bad Magic Number\n");
+			SHOW_BOOT_PROGRESS (-10);
+			do_reset (cmdtp, flag, argc, argv);
+		}
+
+		data = (ulong) & header;
+		len = sizeof (image_header_t);
+
+		checksum = ntohl (hdr->ih_hcrc);
+		hdr->ih_hcrc = 0;
+
+		if (crc32 (0, (char *)data, len) != checksum) {
+			printf ("Bad Header Checksum\n");
+			SHOW_BOOT_PROGRESS (-11);
+			do_reset (cmdtp, flag, argc, argv);
+		}
+
+		SHOW_BOOT_PROGRESS (10);
+
+		print_image_hdr (hdr);
+
+		data = addr + sizeof (image_header_t);
+		len = ntohl (hdr->ih_size);
+
+		if (verify) {
+			ulong csum = 0;
+
+			printf ("   Verifying Checksum ... ");
+			csum = crc32 (0, (char *)data, len);
+			if (csum != ntohl (hdr->ih_dcrc)) {
+				printf ("Bad Data CRC\n");
+				SHOW_BOOT_PROGRESS (-12);
+				do_reset (cmdtp, flag, argc, argv);
+			}
+			printf ("OK\n");
+		}
+
+		SHOW_BOOT_PROGRESS (11);
+
+		if ((hdr->ih_os != IH_OS_LINUX) ||
+		    (hdr->ih_arch != IH_CPU_MICROBLAZE) ||
+		    (hdr->ih_type != IH_TYPE_RAMDISK)) {
+			printf ("No Linux Microblaze Ramdisk Image\n");
+			SHOW_BOOT_PROGRESS (-13);
+			do_reset (cmdtp, flag, argc, argv);
+		}
+
+		/*
+		 * Now check if we have a multifile image
+		 */
+	} else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) {
+		ulong tail = ntohl (len_ptr[0]) % 4;
+
+		SHOW_BOOT_PROGRESS (13);
+
+		/* skip kernel length and terminator */
+		data = (ulong) (&len_ptr[2]);
+		/* skip any additional image length fields */
+		for (i = 1; len_ptr[i]; ++i)
+			data += 4;
+		/* add kernel length, and align */
+		data += ntohl (len_ptr[0]);
+		if (tail) {
+			data += 4 - tail;
+		}
+
+		len = ntohl (len_ptr[1]);
+
+	} else {
+		/*
+		 * no initrd image
+		 */
+		SHOW_BOOT_PROGRESS (14);
+
+		data = 0;
+	}
+
+#ifdef  DEBUG
+	if (!data) {
+		printf ("No initrd\n");
+	}
+#endif
+
+	if (data) {
+		initrd_start = data;
+		initrd_end = initrd_start + len;
+	} else {
+		initrd_start = 0;
+		initrd_end = 0;
+	}
+
+	SHOW_BOOT_PROGRESS (15);
+
+#ifdef DEBUG
+	printf ("## Transferring control to Linux (at address %08lx) ...\n",
+		(ulong) theKernel);
+#endif
+
+	theKernel (commandline);
 }
diff --git a/lib_microblaze/time.c b/lib_microblaze/time.c
index 12e8488..3fa1b11 100644
--- a/lib_microblaze/time.c
+++ b/lib_microblaze/time.c
@@ -1,6 +1,8 @@
 /*
+ * (C) Copyright 2007 Michal Simek
  * (C) Copyright 2004 Atmark Techno, Inc.
  *
+ * Michal  SIMEK <monstr@monstr.eu>
  * Yasushi SHOJI <yashi@atmark-techno.com>
  *
  * See file CREDITS for list of people who contributed to this
@@ -22,6 +24,11 @@
  * MA 02111-1307 USA
  */
 
-void udelay(unsigned long usec)
+#include <common.h>
+
+void udelay (unsigned long usec)
 {
+	int i;
+	i = get_timer (0);
+	while ((get_timer (0) - i) < (usec / 1000)) ;
 }
diff --git a/libfdt/Makefile b/libfdt/Makefile
new file mode 100644
index 0000000..dc41137
--- /dev/null
+++ b/libfdt/Makefile
@@ -0,0 +1,46 @@
+#
+# (C) Copyright 2000-2007
+# 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)libfdt.a
+
+SOBJS	=
+
+COBJS	= fdt.o  fdt_ro.o  fdt_rw.o  fdt_strerror.o  fdt_sw.o  fdt_wip.o
+
+
+SRCS 	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/libfdt/README b/libfdt/README
new file mode 100644
index 0000000..f4cca34
--- /dev/null
+++ b/libfdt/README
@@ -0,0 +1,23 @@
+The libfdt functionality was written by David Gibson.  The original
+source came from the git repository:
+
+URL: 		git://ozlabs.org/home/dgibson/git/libfdt.git
+
+author		David Gibson <dgibson@sneetch.(none)>
+		Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100)
+committer	David Gibson <dgibson@sneetch.(none)>
+	 	Fri, 23 Mar 2007 04:16:54 +0000 (15:16 +1100)
+commit		857f54e79f74429af20c2b5ecc00ee98af6a3b8b
+tree		2f648f0f88225a51ded452968d28b4402df8ade0
+parent		07a12a08005f3b5cd9337900a6551e450c07b515
+
+To adapt for u-boot usage, only the applicable files were copied and
+imported into the u-boot git repository.
+Omitted:
+* GPL - u-boot comes with a copy of the GPL license
+* test subdirectory - not directly useful for u-boot
+
+After importing, other customizations were performed.  See the git log
+for details.
+
+Jerry Van Baren
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
new file mode 100644
index 0000000..4b1c8ab
--- /dev/null
+++ b/libfdt/fdt.c
@@ -0,0 +1,85 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int _fdt_check_header(const void *fdt)
+{
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		/* Complete tree */
+		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+			return -FDT_ERR_BADVERSION;
+		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
+			return -FDT_ERR_BADVERSION;
+	} else if (fdt_magic(fdt) == SW_MAGIC) {
+		/* Unfinished sequential-write blob */
+		if (fdt_size_dt_struct(fdt) == 0)
+			return -FDT_ERR_BADSTATE;
+	} else {
+		return -FDT_ERR_BADMAGIC;
+	}
+
+	return 0;
+}
+
+void *fdt_offset_ptr(const void *fdt, int offset, int len)
+{
+	void *p;
+
+	if (fdt_version(fdt) >= 0x11)
+		if (((offset + len) < offset)
+		    || ((offset + len) > fdt_size_dt_struct(fdt)))
+			return NULL;
+
+	p = _fdt_offset_ptr(fdt, offset);
+
+	if (p + len < p)
+		return NULL;
+	return p;
+}
+
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+{
+	int len = strlen(s) + 1;
+	const char *last = strtab + tabsize - len;
+	const char *p;
+
+	for (p = strtab; p <= last; p++)
+		if (memeq(p, s, len))
+			return p;
+	return NULL;
+}
+
+int fdt_move(const void *fdt, void *buf, int bufsize)
+{
+	int err = _fdt_check_header(fdt);
+
+	if (err)
+		return err;
+
+	if (fdt_totalsize(fdt) > bufsize)
+		return -FDT_ERR_NOSPACE;
+
+	memmove(buf, fdt, fdt_totalsize(fdt));
+	return 0;
+}
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
new file mode 100644
index 0000000..ce01dc7
--- /dev/null
+++ b/libfdt/fdt_ro.c
@@ -0,0 +1,331 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+#define CHECK_HEADER(fdt)	{ \
+	int err; \
+	if ((err = _fdt_check_header(fdt)) != 0) \
+		return err; \
+}
+
+static int offset_streq(const void *fdt, int offset,
+			const char *s, int len)
+{
+	const char *p = fdt_offset_ptr(fdt, offset, len+1);
+
+	if (! p)
+		/* short match */
+		return 0;
+
+	if (memcmp(p, s, len) != 0)
+		return 0;
+
+	if (p[len] != '\0')
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Return a pointer to the string at the given string offset.
+ */
+char *fdt_string(const void *fdt, int stroffset)
+{
+	return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+/*
+ * Return the node offset of the node specified by:
+ *   parentoffset - starting place (0 to start at the root)
+ *   name         - name being searched for
+ *   namelen      - length of the name: typically strlen(name)
+ *
+ * Notes:
+ *   If the start node has subnodes, the subnodes are _not_ searched for the
+ *     requested name.
+ */
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+			       const char *name, int namelen)
+{
+	int level = 0;
+	uint32_t tag;
+	int offset, nextoffset;
+
+	CHECK_HEADER(fdt);
+
+	tag = fdt_next_tag(fdt, parentoffset, &nextoffset, NULL);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADOFFSET;
+
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
+
+		switch (tag) {
+		case FDT_END:
+			return -FDT_ERR_TRUNCATED;
+
+		case FDT_BEGIN_NODE:
+			level++;
+			/*
+			 * If we are nested down levels, ignore the strings
+			 * until we get back to the proper level.
+			 */
+			if (level != 1)
+				continue;
+
+			/* Return the offset if this is "our" string. */
+			if (offset_streq(fdt, offset+FDT_TAGSIZE, name, namelen))
+				return offset;
+			break;
+
+		case FDT_END_NODE:
+			level--;
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (level >= 0);
+
+	return -FDT_ERR_NOTFOUND;
+}
+
+/*
+ * See fdt_subnode_offset_namelen()
+ */
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+		       const char *name)
+{
+	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+/*
+ * Searches for the node corresponding to the given path and returns the
+ * offset of that node.
+ */
+int fdt_path_offset(const void *fdt, const char *path)
+{
+	const char *end = path + strlen(path);
+	const char *p = path;
+	int offset = 0;
+
+	CHECK_HEADER(fdt);
+
+	/* Paths must be absolute */
+	if (*path != '/')
+		return -FDT_ERR_BADPATH;
+
+	while (*p) {
+		const char *q;
+
+		/* Skip path separator(s) */
+		while (*p == '/')
+			p++;
+		if (! *p)
+			return -FDT_ERR_BADPATH;
+
+		/*
+		 * Find the next path separator.  The characters between
+		 * p and q are the next segment of the the path to find.
+		 */
+		q = strchr(p, '/');
+		if (! q)
+			q = end;
+
+		/*
+		 * Find the offset corresponding to the this path segment.
+		 */
+		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+
+		/* Oops, error, abort abort abort */
+		if (offset < 0)
+			return offset;
+
+		p = q;
+	}
+
+	return offset;
+}
+
+/*
+ * Given the offset of a node and a name of a property in that node, return
+ * a pointer to the property struct.
+ */
+struct fdt_property *fdt_get_property(const void *fdt,
+				      int nodeoffset,
+				      const char *name, int *lenp)
+{
+	int level = 0;
+	uint32_t tag;
+	struct fdt_property *prop;
+	int namestroff;
+	int offset, nextoffset;
+	int err;
+
+	if ((err = _fdt_check_header(fdt)) != 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	if (nodeoffset % FDT_TAGSIZE)
+		goto fail;
+
+	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);
+	if (tag != FDT_BEGIN_NODE)
+		goto fail;
+
+	do {
+		offset = nextoffset;
+
+		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
+		switch (tag) {
+		case FDT_END:
+			err = -FDT_ERR_TRUNCATED;
+			goto fail;
+
+		case FDT_BEGIN_NODE:
+			level++;
+			break;
+
+		case FDT_END_NODE:
+			level--;
+			break;
+
+		case FDT_PROP:
+			/*
+			 * If we are nested down levels, ignore the strings
+			 * until we get back to the proper level.
+			 */
+			if (level != 0)
+				continue;
+
+			err = -FDT_ERR_BADSTRUCTURE;
+			prop = fdt_offset_ptr_typed(fdt, offset, prop);
+			if (! prop)
+				goto fail;
+			namestroff = fdt32_to_cpu(prop->nameoff);
+			if (streq(fdt_string(fdt, namestroff), name)) {
+				/* Found it! */
+				int len = fdt32_to_cpu(prop->len);
+				prop = fdt_offset_ptr(fdt, offset,
+						      sizeof(*prop)+len);
+				if (! prop)
+					goto fail;
+
+				if (lenp)
+					*lenp = len;
+
+				return prop;
+			}
+			break;
+
+		case FDT_NOP:
+			break;
+
+		default:
+			err = -FDT_ERR_BADSTRUCTURE;
+			goto fail;
+		}
+	} while (level >= 0);
+
+	err = -FDT_ERR_NOTFOUND;
+fail:
+	if (lenp)
+		*lenp = err;
+	return NULL;
+}
+
+/*
+ * Given the offset of a node and a name of a property in that node, return
+ * a pointer to the property data (ONLY).
+ */
+void *fdt_getprop(const void *fdt, int nodeoffset,
+		  const char *name, int *lenp)
+{
+	const struct fdt_property *prop;
+
+	prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+	if (! prop)
+		return NULL;
+
+	return (void *)prop->data;
+}
+
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset, char **namep)
+{
+	const uint32_t *tagp, *lenp;
+	uint32_t tag;
+	const char *p;
+
+	if (offset % FDT_TAGSIZE)
+		return -1;
+
+	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
+	if (! tagp)
+		return FDT_END; /* premature end */
+	tag = fdt32_to_cpu(*tagp);
+	offset += FDT_TAGSIZE;
+
+	switch (tag) {
+	case FDT_BEGIN_NODE:
+		if(namep)
+			*namep = fdt_offset_ptr(fdt, offset, 1);
+
+		/* skip name */
+		do {
+			p = fdt_offset_ptr(fdt, offset++, 1);
+		} while (p && (*p != '\0'));
+		if (! p)
+			return FDT_END;
+		break;
+	case FDT_PROP:
+		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+		if (! lenp)
+			return FDT_END;
+		/*
+		 * Get the property and set the namep to the name.
+		 */
+		if(namep) {
+			struct fdt_property *prop;
+
+			prop = fdt_offset_ptr_typed(fdt, offset - FDT_TAGSIZE, prop);
+			if (! prop)
+				return -FDT_ERR_BADSTRUCTURE;
+			*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+		}
+		/* skip name offset, length and value */
+		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+		break;
+	}
+
+	if (nextoffset)
+		*nextoffset = ALIGN(offset, FDT_TAGSIZE);
+
+	return tag;
+}
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
new file mode 100644
index 0000000..b33fbf4
--- /dev/null
+++ b/libfdt/fdt_rw.c
@@ -0,0 +1,293 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int rw_check_header(void *fdt)
+{
+	int err;
+
+	if ((err = _fdt_check_header(fdt)))
+		return err;
+	if (fdt_version(fdt) < 0x11)
+		return -FDT_ERR_BADVERSION;
+	if (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8))
+		return -FDT_ERR_BADLAYOUT;
+	if (fdt_off_dt_struct(fdt) <
+	    (fdt_off_mem_rsvmap(fdt) + sizeof(struct fdt_reserve_entry)))
+		return -FDT_ERR_BADLAYOUT;
+	if (fdt_off_dt_strings(fdt) <
+	    (fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt)))
+		return -FDT_ERR_BADLAYOUT;
+	if (fdt_totalsize(fdt) <
+	    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)))
+		return -FDT_ERR_BADLAYOUT;
+	return 0;
+}
+
+#define RW_CHECK_HEADER(fdt) \
+	{ \
+		int err; \
+		if ((err = rw_check_header(fdt)) != 0) \
+			return err; \
+	}
+
+static inline int _blob_data_size(void *fdt)
+{
+	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+}
+
+static int _blob_splice(void *fdt, void *p, int oldlen, int newlen)
+{
+	void *end = fdt + _blob_data_size(fdt);
+
+	if (((p + oldlen) < p) || ((p + oldlen) > end))
+		return -FDT_ERR_BADOFFSET;
+	if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt)))
+		return -FDT_ERR_NOSPACE;
+	memmove(p + newlen, p + oldlen, end - p - oldlen);
+	return 0;
+}
+
+static int _blob_splice_struct(void *fdt, void *p,
+			       int oldlen, int newlen)
+{
+	int delta = newlen - oldlen;
+	int err;
+
+	if ((err = _blob_splice(fdt, p, oldlen, newlen)))
+		return err;
+
+	fdt_set_header(fdt, size_dt_struct, fdt_size_dt_struct(fdt) + delta);
+	fdt_set_header(fdt, off_dt_strings, fdt_off_dt_strings(fdt) + delta);
+	return 0;
+}
+
+static int _blob_splice_string(void *fdt, int newlen)
+{
+	void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+	int err;
+
+	if ((err = _blob_splice(fdt, p, 0, newlen)))
+		return err;
+
+	fdt_set_header(fdt, size_dt_strings, fdt_size_dt_strings(fdt) + newlen);
+	return 0;
+}
+
+static int _find_add_string(void *fdt, const char *s)
+{
+	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
+	const char *p;
+	char *new;
+	int len = strlen(s) + 1;
+	int err;
+
+	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+	if (p)
+		/* found it */
+		return (p - strtab);
+
+	new = strtab + fdt_size_dt_strings(fdt);
+	err = _blob_splice_string(fdt, len);
+	if (err)
+		return err;
+
+	memcpy(new, s, len);
+	return (new - strtab);
+}
+
+static int _resize_property(void *fdt, int nodeoffset, const char *name, int len,
+			    struct fdt_property **prop)
+{
+	int oldlen;
+	int err;
+
+	*prop = fdt_get_property(fdt, nodeoffset, name, &oldlen);
+	if (! (*prop))
+		return oldlen;
+
+	if ((err = _blob_splice_struct(fdt, (*prop)->data,
+				       ALIGN(oldlen, FDT_TAGSIZE),
+				       ALIGN(len, FDT_TAGSIZE))))
+		return err;
+
+	(*prop)->len = cpu_to_fdt32(len);
+	return 0;
+}
+
+static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
+			 struct fdt_property **prop)
+{
+	uint32_t tag;
+	int proplen;
+	int nextoffset;
+	int namestroff;
+	int err;
+
+	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADOFFSET;
+
+	namestroff = _find_add_string(fdt, name);
+	if (namestroff < 0)
+		return namestroff;
+
+	*prop = _fdt_offset_ptr(fdt, nextoffset);
+	proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE);
+
+	err = _blob_splice_struct(fdt, *prop, 0, proplen);
+	if (err)
+		return err;
+
+	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
+	(*prop)->nameoff = cpu_to_fdt32(namestroff);
+	(*prop)->len = cpu_to_fdt32(len);
+	return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+		const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err;
+
+	if ((err = rw_check_header(fdt)))
+		return err;
+
+	err = _resize_property(fdt, nodeoffset, name, len, &prop);
+	if (err == -FDT_ERR_NOTFOUND)
+		err = _add_property(fdt, nodeoffset, name, len, &prop);
+	if (err)
+		return err;
+
+	memcpy(prop->data, val, len);
+	return 0;
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
+{
+	struct fdt_property *prop;
+	int len, proplen;
+
+	RW_CHECK_HEADER(fdt);
+
+	prop = fdt_get_property(fdt, nodeoffset, name, &len);
+	if (! prop)
+		return len;
+
+	proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE);
+	return _blob_splice_struct(fdt, prop, proplen, 0);
+}
+
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+			    const char *name, int namelen)
+{
+	struct fdt_node_header *nh;
+	int offset, nextoffset;
+	int nodelen;
+	int err;
+	uint32_t tag;
+	uint32_t *endtag;
+
+	RW_CHECK_HEADER(fdt);
+
+	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
+	if (offset >= 0)
+		return -FDT_ERR_EXISTS;
+	else if (offset != -FDT_ERR_NOTFOUND)
+		return offset;
+
+	/* Try to place the new node after the parent's properties */
+	fdt_next_tag(fdt, parentoffset, &nextoffset, NULL); /* skip the BEGIN_NODE */
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
+	} while (tag == FDT_PROP);
+
+	nh = _fdt_offset_ptr(fdt, offset);
+	nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE;
+
+	err = _blob_splice_struct(fdt, nh, 0, nodelen);
+	if (err)
+		return err;
+
+	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+	memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE));
+	memcpy(nh->name, name, namelen);
+	endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE);
+	*endtag = cpu_to_fdt32(FDT_END_NODE);
+
+	return offset;
+}
+
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+	return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_del_node(void *fdt, int nodeoffset)
+{
+	int endoffset;
+
+	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	if (endoffset < 0)
+		return endoffset;
+
+	return _blob_splice_struct(fdt, _fdt_offset_ptr(fdt, nodeoffset),
+				   endoffset - nodeoffset, 0);
+}
+
+int fdt_open_into(void *fdt, void *buf, int bufsize)
+{
+	int err;
+
+	err = fdt_move(fdt, buf, bufsize);
+	if (err)
+		return err;
+
+	fdt = buf;
+
+	fdt_set_header(fdt, totalsize, bufsize);
+
+	/* FIXME: re-order if necessary */
+
+	err = rw_check_header(fdt);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+int fdt_pack(void *fdt)
+{
+	int err;
+
+	err = rw_check_header(fdt);
+	if (err)
+		return err;
+
+	/* FIXME: pack components */
+	fdt_set_header(fdt, totalsize, _blob_data_size(fdt));
+	return 0;
+}
diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c
new file mode 100644
index 0000000..7f231ce
--- /dev/null
+++ b/libfdt/fdt_strerror.c
@@ -0,0 +1,64 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+struct errtabent {
+	const char *str;
+};
+
+#define ERRTABENT(val) \
+	[(val)] = { .str = #val, }
+
+static struct errtabent errtable[] = {
+	ERRTABENT(FDT_ERR_NOTFOUND),
+	ERRTABENT(FDT_ERR_EXISTS),
+	ERRTABENT(FDT_ERR_NOSPACE),
+
+	ERRTABENT(FDT_ERR_BADOFFSET),
+	ERRTABENT(FDT_ERR_BADPATH),
+	ERRTABENT(FDT_ERR_BADSTATE),
+
+	ERRTABENT(FDT_ERR_TRUNCATED),
+	ERRTABENT(FDT_ERR_BADMAGIC),
+	ERRTABENT(FDT_ERR_BADVERSION),
+	ERRTABENT(FDT_ERR_BADSTRUCTURE),
+	ERRTABENT(FDT_ERR_BADLAYOUT),
+};
+#define ERRTABSIZE	(sizeof(errtable) / sizeof(errtable[0]))
+
+const char *fdt_strerror(int errval)
+{
+	if (errval > 0)
+		return "<valid offset/length>";
+	else if (errval == 0)
+		return "<no error>";
+	else if (errval > -ERRTABSIZE) {
+		const char *s = errtable[-errval].str;
+
+		if (s)
+			return s;
+	}
+
+	return "<unknown error>";
+}
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
new file mode 100644
index 0000000..672f4dd
--- /dev/null
+++ b/libfdt/fdt_sw.c
@@ -0,0 +1,226 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int check_header_sw(void *fdt)
+{
+	if (fdt_magic(fdt) != SW_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	return 0;
+}
+
+static void *grab_space(void *fdt, int len)
+{
+	int offset = fdt_size_dt_struct(fdt);
+	int spaceleft;
+
+	spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
+		- fdt_size_dt_strings(fdt);
+
+	if ((offset + len < offset) || (offset + len > spaceleft))
+		return NULL;
+
+	fdt_set_header(fdt, size_dt_struct, offset + len);
+	return fdt_offset_ptr(fdt, offset, len);
+}
+
+int fdt_create(void *buf, int bufsize)
+{
+	void *fdt = buf;
+
+	if (bufsize < sizeof(struct fdt_header))
+		return -FDT_ERR_NOSPACE;
+
+	memset(buf, 0, bufsize);
+
+	fdt_set_header(fdt, magic, SW_MAGIC);
+	fdt_set_header(fdt, version, FDT_LAST_SUPPORTED_VERSION);
+	fdt_set_header(fdt, last_comp_version, FDT_FIRST_SUPPORTED_VERSION);
+	fdt_set_header(fdt, totalsize, bufsize);
+
+	fdt_set_header(fdt, off_mem_rsvmap, ALIGN(sizeof(struct fdt_header),
+					      sizeof(struct fdt_reserve_entry)));
+	fdt_set_header(fdt, off_dt_struct, fdt_off_mem_rsvmap(fdt));
+	fdt_set_header(fdt, off_dt_strings, bufsize);
+
+	return 0;
+}
+
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
+{
+	struct fdt_reserve_entry *re;
+	int err = check_header_sw(fdt);
+	int offset;
+
+	if (err)
+		return err;
+	if (fdt_size_dt_struct(fdt))
+		return -FDT_ERR_BADSTATE;
+
+	offset = fdt_off_dt_struct(fdt);
+	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
+		return -FDT_ERR_NOSPACE;
+
+	re = (struct fdt_reserve_entry *)((void *)fdt + offset);
+	re->address = cpu_to_fdt64(addr);
+	re->size = cpu_to_fdt64(size);
+
+	fdt_set_header(fdt, off_dt_struct, offset + sizeof(*re));
+
+	return 0;
+}
+
+int fdt_finish_reservemap(void *fdt)
+{
+	return fdt_add_reservemap_entry(fdt, 0, 0);
+}
+
+int fdt_begin_node(void *fdt, const char *name)
+{
+	struct fdt_node_header *nh;
+	int err = check_header_sw(fdt);
+	int namelen = strlen(name) + 1;
+
+	if (err)
+		return err;
+
+	nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE));
+	if (! nh)
+		return -FDT_ERR_NOSPACE;
+
+	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+	memcpy(nh->name, name, namelen);
+	return 0;
+}
+
+int fdt_end_node(void *fdt)
+{
+	uint32_t *en;
+	int err = check_header_sw(fdt);
+
+	if (err)
+		return err;
+
+	en = grab_space(fdt, FDT_TAGSIZE);
+	if (! en)
+		return -FDT_ERR_NOSPACE;
+
+	*en = cpu_to_fdt32(FDT_END_NODE);
+	return 0;
+}
+
+static int find_add_string(void *fdt, const char *s)
+{
+	char *strtab = (char *)fdt + fdt_totalsize(fdt);
+	const char *p;
+	int strtabsize = fdt_size_dt_strings(fdt);
+	int len = strlen(s) + 1;
+	int struct_top, offset;
+
+	p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+	if (p)
+		return p - strtab;
+
+	/* Add it */
+	offset = -strtabsize - len;
+	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+	if (fdt_totalsize(fdt) + offset < struct_top)
+		return 0; /* no more room :( */
+
+	memcpy(strtab + offset, s, len);
+	fdt_set_header(fdt, size_dt_strings, strtabsize + len);
+	return offset;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err = check_header_sw(fdt);
+	int nameoff;
+
+	if (err)
+		return err;
+
+	nameoff = find_add_string(fdt, name);
+	if (nameoff == 0)
+		return -FDT_ERR_NOSPACE;
+
+	prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE));
+	if (! prop)
+		return -FDT_ERR_NOSPACE;
+
+	prop->tag = cpu_to_fdt32(FDT_PROP);
+	prop->nameoff = cpu_to_fdt32(nameoff);
+	prop->len = cpu_to_fdt32(len);
+	memcpy(prop->data, val, len);
+	return 0;
+}
+
+int fdt_finish(void *fdt)
+{
+	int err = check_header_sw(fdt);
+	char *p = (char *)fdt;
+	uint32_t *end;
+	int oldstroffset, newstroffset;
+	uint32_t tag;
+	int offset, nextoffset;
+
+	if (err)
+		return err;
+
+	/* Add terminator */
+	end = grab_space(fdt, sizeof(*end));
+	if (! end)
+		return -FDT_ERR_NOSPACE;
+	*end = cpu_to_fdt32(FDT_END);
+
+	/* Relocate the string table */
+	oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
+	newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
+	fdt_set_header(fdt, off_dt_strings, newstroffset);
+
+	/* Walk the structure, correcting string offsets */
+	offset = 0;
+	while ((tag = fdt_next_tag(fdt, offset, &nextoffset, NULL)) != FDT_END) {
+		if (tag == FDT_PROP) {
+			struct fdt_property *prop = fdt_offset_ptr(fdt, offset,
+								   sizeof(*prop));
+			int nameoff;
+
+			if (! prop)
+				return -FDT_ERR_BADSTRUCTURE;
+
+			nameoff = fdt32_to_cpu(prop->nameoff);
+			nameoff += fdt_size_dt_strings(fdt);
+			prop->nameoff = cpu_to_fdt32(nameoff);
+		}
+		offset = nextoffset;
+	}
+
+	/* Finally, adjust the header */
+	fdt_set_header(fdt, totalsize, newstroffset + fdt_size_dt_strings(fdt));
+	fdt_set_header(fdt, magic, FDT_MAGIC);
+	return 0;
+}
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
new file mode 100644
index 0000000..261b9b0
--- /dev/null
+++ b/libfdt/fdt_wip.c
@@ -0,0 +1,112 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+			const void *val, int len)
+{
+	void *propval;
+	int proplen;
+
+	propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
+	if (! propval)
+		return proplen;
+
+	if (proplen != len)
+		return -FDT_ERR_NOSPACE;
+
+	memcpy(propval, val, len);
+	return 0;
+}
+
+static void nop_region(void *start, int len)
+{
+	uint32_t *p;
+
+	for (p = start; (void *)p < (start + len); p++)
+		*p = cpu_to_fdt32(FDT_NOP);
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
+{
+	struct fdt_property *prop;
+	int len;
+
+	prop = fdt_get_property(fdt, nodeoffset, name, &len);
+	if (! prop)
+		return len;
+
+	nop_region(prop, len + sizeof(*prop));
+
+	return 0;
+}
+
+int _fdt_node_end_offset(void *fdt, int nodeoffset)
+{
+	int level = 0;
+	uint32_t tag;
+	int offset, nextoffset;
+
+	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);
+	if (tag != FDT_BEGIN_NODE)
+		return -FDT_ERR_BADOFFSET;
+	do {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);
+
+		switch (tag) {
+		case FDT_END:
+			return offset;
+
+		case FDT_BEGIN_NODE:
+			level++;
+			break;
+
+		case FDT_END_NODE:
+			level--;
+			break;
+
+		case FDT_PROP:
+		case FDT_NOP:
+			break;
+
+		default:
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	} while (level >= 0);
+
+	return nextoffset;
+}
+
+int fdt_nop_node(void *fdt, int nodeoffset)
+{
+	int endoffset;
+
+	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+	if (endoffset < 0)
+		return endoffset;
+
+	nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), endoffset - nodeoffset);
+	return 0;
+}
diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h
new file mode 100644
index 0000000..cc9633c
--- /dev/null
+++ b/libfdt/libfdt_internal.h
@@ -0,0 +1,40 @@
+#ifndef _LIBFDT_INTERNAL_H
+#define _LIBFDT_INTERNAL_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <fdt.h>
+
+#define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
+#define PALIGN(p, a)	((void *)ALIGN((unsigned long)(p), (a)))
+
+#define memeq(p, q, n)	(memcmp((p), (q), (n)) == 0)
+#define streq(p, q)	(strcmp((p), (q)) == 0)
+
+int _fdt_check_header(const void *fdt);
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
+int _fdt_node_end_offset(void *fdt, int nodeoffset);
+
+static inline void *_fdt_offset_ptr(const struct fdt_header *fdt, int offset)
+{
+	return (void *)fdt + fdt_off_dt_struct(fdt) + offset;
+}
+
+#define SW_MAGIC		(~FDT_MAGIC)
+
+#endif /* _LIBFDT_INTERNAL_H */
diff --git a/microblaze_config.mk b/microblaze_config.mk
index b3ac8e0..06ddefa 100644
--- a/microblaze_config.mk
+++ b/microblaze_config.mk
@@ -22,7 +22,7 @@
 # MA 02111-1307 USA
 #
 
-PLATFORM_CPPFLAGS += -ffixed-r31
+PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__
 
 ifdef CONFIG_MICROBLAZE_HARD_MULT
 PLATFORM_CPPFLAGS += -mno-xl-soft-mul