Merge with /home/wd/git/u-boot/custodian/u-boot-mpc85xx
diff --git a/board/amcc/sequoia/init.S b/board/amcc/sequoia/init.S
index 45bcd4b..5fe3af9 100644
--- a/board/amcc/sequoia/init.S
+++ b/board/amcc/sequoia/init.S
@@ -126,6 +126,9 @@
 	/* TLB-entry for peripherals */
 	tlbentry( 0xEF000000, SZ_16M, 0xEF000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I)
 
+	/* TLB-entry PCI IO Space - from sr@denx.de */
+	tlbentry(0xE8000000, SZ_64K, 0xE8000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I)
+
 	tlbtab_end
 
 #if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
diff --git a/board/icecube/icecube.c b/board/icecube/icecube.c
index c027f6f..07ba245 100644
--- a/board/icecube/icecube.c
+++ b/board/icecube/icecube.c
@@ -28,10 +28,7 @@
 #include <mpc5xxx.h>
 #include <pci.h>
 #include <asm/processor.h>
-
-#if defined(CONFIG_OF_FLAT_TREE)
-#include <ft_build.h>
-#endif
+#include <libfdt.h>
 
 #if defined(CONFIG_LITE5200B)
 #include "mt46v32m16.h"
@@ -386,7 +383,7 @@
 }
 #endif
 
-#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP)
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 void
 ft_board_setup(void *blob, bd_t *bd)
 {
diff --git a/board/jupiter/jupiter.c b/board/jupiter/jupiter.c
index b227487..efdc333 100644
--- a/board/jupiter/jupiter.c
+++ b/board/jupiter/jupiter.c
@@ -28,11 +28,7 @@
 #include <mpc5xxx.h>
 #include <pci.h>
 #include <asm/processor.h>
-
-#if defined(CONFIG_OF_FLAT_TREE)
-#include <ft_build.h>
-#endif
-
+#include <libfdt.h>
 
 #define SDRAM_DDR	0
 #if 1
@@ -308,7 +304,7 @@
 }
 #endif
 
-#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP)
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 void
 ft_board_setup(void *blob, bd_t *bd)
 {
diff --git a/board/motionpro/motionpro.c b/board/motionpro/motionpro.c
index 6eb5fe9..f83998e 100644
--- a/board/motionpro/motionpro.c
+++ b/board/motionpro/motionpro.c
@@ -29,9 +29,7 @@
 #include <common.h>
 #include <mpc5xxx.h>
 #include <miiphy.h>
-#if defined(CONFIG_OF_FLAT_TREE)
-#include <ft_build.h>
-#endif
+#include <libfdt.h>
 
 #if defined(CONFIG_STATUS_LED)
 #include <status_led.h>
@@ -196,12 +194,12 @@
 }
 
 
-#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP)
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 void ft_board_setup(void *blob, bd_t *bd)
 {
 	ft_cpu_setup(blob, bd);
 }
-#endif /* defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) */
+#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
 
 
 #if defined(CONFIG_STATUS_LED)
diff --git a/board/tqm5200/tqm5200.c b/board/tqm5200/tqm5200.c
index 51f4aeb..21f67aa 100644
--- a/board/tqm5200/tqm5200.c
+++ b/board/tqm5200/tqm5200.c
@@ -31,10 +31,7 @@
 #include <mpc5xxx.h>
 #include <pci.h>
 #include <asm/processor.h>
-
-#if defined(CONFIG_OF_FLAT_TREE)
-#include <ft_build.h>
-#endif
+#include <libfdt.h>
 
 #ifdef CONFIG_VIDEO_SM501
 #include <sm501.h>
@@ -780,9 +777,9 @@
 
 #endif /* CONFIG_VIDEO_SM501 */
 
-#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP)
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
 void ft_board_setup(void *blob, bd_t *bd)
 {
 	ft_cpu_setup(blob, bd);
 }
-#endif /* defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) */
+#endif /* defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) */
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index bcb927f..9f5e0b4 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -817,27 +817,32 @@
 		int i;
 
 		/* skip kernel length, initrd length, and terminator */
-		of_data = (ulong)(&len_ptr[3]);
+		of_flat_tree = (char *)(&len_ptr[3]);
 		/* skip any additional image length fields */
 		for (i=2; len_ptr[i]; ++i)
-			of_data += 4;
+			of_flat_tree += 4;
 		/* add kernel length, and align */
-		of_data += ntohl(len_ptr[0]);
+		of_flat_tree += ntohl(len_ptr[0]);
 		if (tail) {
-			of_data += 4 - tail;
+			of_flat_tree += 4 - tail;
 		}
 
 		/* add initrd length, and align */
 		tail = ntohl(len_ptr[1]) % 4;
-		of_data += ntohl(len_ptr[1]);
+		of_flat_tree += ntohl(len_ptr[1]);
 		if (tail) {
-			of_data += 4 - tail;
+			of_flat_tree += 4 - tail;
 		}
 
+		/* move the blob if it is in flash (set of_data to !null) */
+		if (addr2info ((ulong)of_flat_tree) != NULL)
+			of_data = (ulong)of_flat_tree;
+
+
 #if defined(CONFIG_OF_FLAT_TREE)
-		if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {
+		if (*((ulong *)(of_flat_tree)) != OF_DT_HEADER) {
 #else
-		if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) {
+		if (fdt_check_header (of_flat_tree) != 0) {
 #endif
 			puts ("ERROR: image is not a fdt - "
 				"must RESET the board to recover.\n");
@@ -845,9 +850,11 @@
 		}
 
 #if defined(CONFIG_OF_FLAT_TREE)
-		if (((struct boot_param_header *)of_data)->totalsize != ntohl(len_ptr[2])) {
+		if (((struct boot_param_header *)of_flat_tree)->totalsize !=
+			ntohl (len_ptr[2])) {
 #else
-		if (be32_to_cpu(fdt_totalsize(of_data)) !=  ntohl(len_ptr[2])) {
+		if (be32_to_cpu (fdt_totalsize (of_flat_tree)) !=
+			ntohl(len_ptr[2])) {
 #endif
 			puts ("ERROR: fdt size != image size - "
 				"must RESET the board to recover.\n");
@@ -957,34 +964,37 @@
 				"must RESET the board to recover.\n");
 			do_reset (cmdtp, flag, argc, argv);
 		}
+		puts ("OK\n");
 	}
 	/*
 	 * Add the chosen node if it doesn't exist, add the env and bd_t
 	 * if the user wants it (the logic is in the subroutines).
 	 */
-	if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
-		puts ("ERROR: /chosen node create failed - "
-			"must RESET the board to recover.\n");
-		do_reset (cmdtp, flag, argc, argv);
-	}
+	if (of_flat_tree) {
+		if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) {
+			puts ("ERROR: /chosen node create failed - "
+				"must RESET the board to recover.\n");
+			do_reset (cmdtp, flag, argc, argv);
+		}
 #ifdef CONFIG_OF_HAS_UBOOT_ENV
-	if (fdt_env(of_flat_tree) < 0) {
-		puts ("ERROR: /u-boot-env node create failed - "
-			"must RESET the board to recover.\n");
-		do_reset (cmdtp, flag, argc, argv);
-	}
+		if (fdt_env(of_flat_tree) < 0) {
+			puts ("ERROR: /u-boot-env node create failed - "
+				"must RESET the board to recover.\n");
+			do_reset (cmdtp, flag, argc, argv);
+		}
 #endif
 #ifdef CONFIG_OF_HAS_BD_T
-	if (fdt_bd_t(of_flat_tree) < 0) {
-		puts ("ERROR: /bd_t node create failed - "
-			"must RESET the board to recover.\n");
-		do_reset (cmdtp, flag, argc, argv);
-	}
+		if (fdt_bd_t(of_flat_tree) < 0) {
+			puts ("ERROR: /bd_t node create failed - "
+				"must RESET the board to recover.\n");
+			do_reset (cmdtp, flag, argc, argv);
+		}
 #endif
 #ifdef CONFIG_OF_BOARD_SETUP
-	/* Call the board-specific fixup routine */
-	ft_board_setup(of_flat_tree, gd->bd);
+		/* Call the board-specific fixup routine */
+		ft_board_setup(of_flat_tree, gd->bd);
 #endif
+	}
 #endif /* CONFIG_OF_LIBFDT */
 #if defined(CONFIG_OF_FLAT_TREE)
 #ifdef CFG_BOOTMAPSZ
@@ -1011,6 +1021,7 @@
 		printf ("   Loading Device Tree to %08lx, end %08lx ... ",
 			of_start, of_start + of_len - 1);
 		memmove ((void *)of_start, (void *)of_data, of_len);
+		puts ("OK\n");
 	}
 	/*
 	 * Create the /chosen node and modify the blob with board specific
diff --git a/cpu/mpc5xxx/cpu.c b/cpu/mpc5xxx/cpu.c
index 1eac2bb..7f16b92 100644
--- a/cpu/mpc5xxx/cpu.c
+++ b/cpu/mpc5xxx/cpu.c
@@ -29,10 +29,12 @@
 #include <watchdog.h>
 #include <command.h>
 #include <mpc5xxx.h>
+#include <asm/io.h>
 #include <asm/processor.h>
 
-#if defined(CONFIG_OF_FLAT_TREE)
-#include <ft_build.h>
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <libfdt_env.h>
 #endif
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -111,29 +113,43 @@
 
 /* ------------------------------------------------------------------------- */
 
-#ifdef CONFIG_OF_FLAT_TREE
-void
-ft_cpu_setup(void *blob, bd_t *bd)
+#ifdef CONFIG_OF_LIBFDT
+static void do_fixup(void *fdt, const char *node, const char *prop,
+		     const void *val, int len, int create)
 {
-	u32 *p;
-	int len;
+#if defined(DEBUG)
+	int i;
+	debug("Updating property '%s/%s' = ", node, prop);
+	for (i = 0; i < len; i++)
+		debug(" %.2x", *(u8*)(val+i));
+	debug("\n");
+#endif
+	int rc = fdt_find_and_setprop(fdt, node, prop, val, len, create);
+	if (rc)
+		printf("Unable to update property %s:%s, err=%s\n",
+		       node, prop, fdt_strerror(rc));
+}
 
-	/* Core XLB bus frequency */
-	p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
-	if (p != NULL)
-		*p = cpu_to_be32(bd->bi_busfreq);
+static void do_fixup_u32(void *fdt, const char *node, const char *prop,
+			 u32 val, int create)
+{
+	val = cpu_to_fdt32(val);
+	do_fixup(fdt, node, prop, &val, sizeof(val), create);
+}
 
-	/* SOC peripherals use the IPB bus frequency */
-	p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len);
-	if (p != NULL)
-		*p = cpu_to_be32(bd->bi_ipbfreq);
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+	int div = in_8((void*)CFG_MBAR + 0x204) & 0x0020 ? 8 : 4;
+	char * cpu_path = "/cpus/" OF_CPU;
+	char * eth_path = "/" OF_SOC "/ethernet@3000";
 
-	p = ft_get_prop(blob, "/" OF_SOC "/ethernet@3000/mac-address", &len);
-	if (p != NULL)
-		memcpy(p, bd->bi_enetaddr, 6);
-
-	p = ft_get_prop(blob, "/" OF_SOC "/ethernet@3000/local-mac-address", &len);
-	if (p != NULL)
-		memcpy(p, bd->bi_enetaddr, 6);
+	do_fixup_u32(blob, cpu_path, "timebase-frequency", OF_TBCLK, 1);
+	do_fixup_u32(blob, cpu_path, "bus-frequency", bd->bi_busfreq, 1);
+	do_fixup_u32(blob, cpu_path, "clock-frequency", bd->bi_intfreq, 1);
+	do_fixup_u32(blob, "/" OF_SOC, "bus-frequency", bd->bi_ipbfreq, 1);
+	do_fixup_u32(blob, "/" OF_SOC, "system-frequency",
+			bd->bi_busfreq*div, 1);
+	do_fixup(blob, eth_path, "mac-address", bd->bi_enetaddr, 6, 0);
+	do_fixup(blob, eth_path, "local-mac-address", bd->bi_enetaddr, 6, 0);
 }
 #endif
diff --git a/drivers/Makefile b/drivers/Makefile
index 3ee6312..6bf05cc 100755
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -43,7 +43,7 @@
 	  sed13806.o sed156x.o \
 	  serial.o serial_max3100.o \
 	  serial_pl010.o serial_pl011.o serial_xuartlite.o \
-	  sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
+	  sil680.o sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
 	  status_led.o sym53c8xx.o systemace.o ahci.o \
 	  ti_pci1410a.o tigon3.o tsec.o \
 	  tsi108_eth.o tsi108_i2c.o tsi108_pci.o \
diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c
index 2378553..acfda83 100644
--- a/drivers/pci_auto.c
+++ b/drivers/pci_auto.c
@@ -28,6 +28,11 @@
 
 #define	PCIAUTO_IDE_MODE_MASK		0x05
 
+/* the user can define CFG_PCI_CACHE_LINE_SIZE to avoid problems */
+#ifndef CFG_PCI_CACHE_LINE_SIZE
+#define CFG_PCI_CACHE_LINE_SIZE	8
+#endif
+
 /*
  *
  */
@@ -150,7 +155,8 @@
 	}
 
 	pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat);
-	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
+		CFG_PCI_CACHE_LINE_SIZE);
 	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
 }
 
diff --git a/drivers/sil680.c b/drivers/sil680.c
new file mode 100644
index 0000000..a6143df
--- /dev/null
+++ b/drivers/sil680.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2007
+ * Gary Jennejohn, DENX Software Engineering, garyj@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
+ *
+ */
+/* sil680.c - ide support functions for the Sil0680A controller */
+
+/*
+ * The following parameters must be defined in the configuration file
+ * of the target board:
+ *
+ * #define CFG_IDE_SIL680
+ *
+ * #define CONFIG_PCI_PNP
+ * NOTE it may also be necessary to define this if the default of 8 is
+ * incorrect for the target board (e.g. the sequoia board requires 0).
+ * #define CFG_PCI_CACHE_LINE_SIZE	0
+ *
+ * #define CONFIG_CMD_IDE
+ * #undef  CONFIG_IDE_8xx_DIRECT
+ * #undef  CONFIG_IDE_LED
+ * #undef  CONFIG_IDE_RESET
+ * #define CONFIG_IDE_PREINIT
+ * #define CFG_IDE_MAXBUS		2 - modify to suit
+ * #define CFG_IDE_MAXDEVICE	(CFG_IDE_MAXBUS*2) - modify to suit
+ * #define CFG_ATA_BASE_ADDR	0
+ * #define CFG_ATA_IDE0_OFFSET	0
+ * #define CFG_ATA_IDE1_OFFSET	0
+ * #define CFG_ATA_DATA_OFFSET	0
+ * #define CFG_ATA_REG_OFFSET	0
+ * #define CFG_ATA_ALT_OFFSET	0x0004
+ *
+ * The mapping for PCI IO-space.
+ * NOTE this is the value for the sequoia board. Modify to suit.
+ * #define CFG_PCI0_IO_SPACE   0xE8000000
+ */
+
+#include <common.h>
+#if defined(CFG_IDE_SIL680)
+#include <ata.h>
+#include <ide.h>
+#include <pci.h>
+
+extern ulong ide_bus_offset[CFG_IDE_MAXBUS];
+
+int ide_preinit (void)
+{
+	int status;
+	pci_dev_t devbusfn;
+	int l;
+
+	status = 1;
+	for (l = 0; l < CFG_IDE_MAXBUS; l++) {
+		ide_bus_offset[l] = -ATA_STATUS;
+	}
+	devbusfn = pci_find_device (0x1095, 0x0680, 0);
+	if (devbusfn != -1) {
+		status = 0;
+
+		pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0,
+				       (u32 *) &ide_bus_offset[0]);
+		ide_bus_offset[0] &= 0xfffffff8;
+		ide_bus_offset[0] += CFG_PCI0_IO_SPACE;
+		pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_2,
+				       (u32 *) &ide_bus_offset[1]);
+		ide_bus_offset[1] &= 0xfffffff8;
+		ide_bus_offset[1] += CFG_PCI0_IO_SPACE;
+		/* init various things - taken from the Linux driver */
+		/* set PIO mode */
+		pci_write_config_byte(devbusfn, 0x80, 0x00);
+		pci_write_config_byte(devbusfn, 0x84, 0x00);
+		/* IDE0 */
+		pci_write_config_byte(devbusfn,  0xA1, 0x02);
+		pci_write_config_word(devbusfn,  0xA2, 0x328A);
+		pci_write_config_dword(devbusfn, 0xA4, 0x62DD62DD);
+		pci_write_config_dword(devbusfn, 0xA8, 0x43924392);
+		pci_write_config_dword(devbusfn, 0xAC, 0x40094009);
+		/* IDE1 */
+		pci_write_config_byte(devbusfn,  0xB1, 0x02);
+		pci_write_config_word(devbusfn,  0xB2, 0x328A);
+		pci_write_config_dword(devbusfn, 0xB4, 0x62DD62DD);
+		pci_write_config_dword(devbusfn, 0xB8, 0x43924392);
+		pci_write_config_dword(devbusfn, 0xBC, 0x40094009);
+	}
+	return (status);
+}
+
+void ide_set_reset (int flag) {
+	return;
+}
+
+#endif /* CFG_IDE_SIL680 */
diff --git a/include/configs/IceCube.h b/include/configs/IceCube.h
index bdd92ba..4c16d22 100644
--- a/include/configs/IceCube.h
+++ b/include/configs/IceCube.h
@@ -178,7 +178,7 @@
 #endif /* CONFIG_MPC5200 */
 
 /* pass open firmware flat tree */
-#define CONFIG_OF_FLAT_TREE	1
+#define CONFIG_OF_LIBFDT	1
 #define CONFIG_OF_BOARD_SETUP	1
 
 #define OF_CPU			"PowerPC,5200@0"
diff --git a/include/configs/TQM5200.h b/include/configs/TQM5200.h
index c08173b..e0c9d81 100644
--- a/include/configs/TQM5200.h
+++ b/include/configs/TQM5200.h
@@ -701,7 +701,7 @@
  * Open firmware flat tree support
  *-----------------------------------------------------------------------
  */
-#define CONFIG_OF_FLAT_TREE	1
+#define CONFIG_OF_LIBFDT	1
 #define CONFIG_OF_BOARD_SETUP	1
 
 #define OF_CPU			"PowerPC,5200@0"
diff --git a/include/configs/jupiter.h b/include/configs/jupiter.h
index 4070ab9..b7100e9 100644
--- a/include/configs/jupiter.h
+++ b/include/configs/jupiter.h
@@ -145,7 +145,7 @@
 
 #if 0
 /* pass open firmware flat tree */
-#define CONFIG_OF_FLAT_TREE	1
+#define CONFIG_OF_LIBFDT	1
 #define CONFIG_OF_BOARD_SETUP	1
 
 #define OF_CPU			"PowerPC,5200@0"
diff --git a/include/configs/motionpro.h b/include/configs/motionpro.h
index 82827c6..9a21632 100644
--- a/include/configs/motionpro.h
+++ b/include/configs/motionpro.h
@@ -417,7 +417,7 @@
 #define CFG_RESET_ADDRESS	0xfff00100
 
 /* pass open firmware flat tree */
-#define CONFIG_OF_FLAT_TREE	1
+#define CONFIG_OF_LIBFDT	1
 #define CONFIG_OF_BOARD_SETUP	1
 
 #define OF_CPU			"PowerPC,5200@0"
diff --git a/include/configs/sequoia.h b/include/configs/sequoia.h
index 824a812..c2e1386 100644
--- a/include/configs/sequoia.h
+++ b/include/configs/sequoia.h
@@ -400,7 +400,8 @@
  *----------------------------------------------------------------------*/
 /* General PCI */
 #define CONFIG_PCI			/* include pci support	        */
-#undef CONFIG_PCI_PNP			/* do (not) pci plug-and-play   */
+#define CONFIG_PCI_PNP			/* do pci plug-and-play   */
+#define CFG_PCI_CACHE_LINE_SIZE	0 /* to avoid problems with PNP */
 #define CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup  */
 #define CFG_PCI_TARGBASE        0x80000000 /* PCIaddr mapped to CFG_PCI_MEMBASE*/
 
diff --git a/include/libfdt.h b/include/libfdt.h
index 340e89d..38c65a9 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -140,6 +140,8 @@
 	})
 #define fdt_setprop_string(fdt, nodeoffset, name, str) \
 	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
+			 const void *val, int len, int create);
 int fdt_delprop(void *fdt, int nodeoffset, const char *name);
 int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 			    const char *name, int namelen);
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
index 693bfe4..55fcc41 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -188,6 +188,32 @@
 	return 0;
 }
 
+/**
+ * fdt_find_and_setprop: Find a node and set it's property
+ *
+ * @fdt: ptr to device tree
+ * @node: path of node
+ * @prop: property name
+ * @val: ptr to new value
+ * @len: length of new property value
+ * @create: flag to create the property if it doesn't exist
+ *
+ * Convenience function to directly set a property given the path to the node.
+ */
+int fdt_find_and_setprop(void *fdt, const char *node, const char *prop,
+			 const void *val, int len, int create)
+{
+	int nodeoff = fdt_find_node_by_path(fdt, node);
+
+	if (nodeoff < 0)
+		return nodeoff;
+
+	if ((!create) && (fdt_get_property(fdt, nodeoff, prop, 0) == NULL))
+		return 0; /* create flag not set; so exit quietly */
+
+	return fdt_setprop(fdt, nodeoff, prop, val, len);
+}
+
 int fdt_delprop(void *fdt, int nodeoffset, const char *name)
 {
 	struct fdt_property *prop;