Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
diff --git a/README b/README
index b1b3e17..3780564 100644
--- a/README
+++ b/README
@@ -1209,7 +1209,23 @@
 			If this option is set, the driver enables cache flush.
 
 - TPM Support:
-		CONFIG_GENERIC_LPC_TPM
+		CONFIG_TPM
+		Support TPM devices.
+
+		CONFIG_TPM_TIS_I2C
+		Support for i2c bus TPM devices. Only one device
+		per system is supported at this time.
+
+			CONFIG_TPM_TIS_I2C_BUS_NUMBER
+			Define the the i2c bus number for the TPM device
+
+			CONFIG_TPM_TIS_I2C_SLAVE_ADDRESS
+			Define the TPM's address on the i2c bus
+
+			CONFIG_TPM_TIS_I2C_BURST_LIMITATION
+			Define the burst count bytes upper limit
+
+		CONFIG_TPM_TIS_LPC
 		Support for generic parallel port TPM devices. Only one device
 		per system is supported at this time.
 
diff --git a/arch/arm/cpu/armv7/omap-common/boot-common.c b/arch/arm/cpu/armv7/omap-common/boot-common.c
index bff7e9c..76ae1b6 100644
--- a/arch/arm/cpu/armv7/omap-common/boot-common.c
+++ b/arch/arm/cpu/armv7/omap-common/boot-common.c
@@ -25,6 +25,45 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+void save_omap_boot_params(void)
+{
+	u32 rom_params = *((u32 *)OMAP_SRAM_SCRATCH_BOOT_PARAMS);
+	u8 boot_device;
+	u32 dev_desc, dev_data;
+
+	if ((rom_params <  NON_SECURE_SRAM_START) ||
+	    (rom_params > NON_SECURE_SRAM_END))
+		return;
+
+	/*
+	 * rom_params can be type casted to omap_boot_parameters and
+	 * used. But it not correct to assume that romcode structure
+	 * encoding would be same as u-boot. So use the defined offsets.
+	 */
+	gd->arch.omap_boot_params.omap_bootdevice = boot_device =
+				   *((u8 *)(rom_params + BOOT_DEVICE_OFFSET));
+
+	gd->arch.omap_boot_params.ch_flags =
+				*((u8 *)(rom_params + CH_FLAGS_OFFSET));
+
+	if ((boot_device >= MMC_BOOT_DEVICES_START) &&
+	    (boot_device <= MMC_BOOT_DEVICES_END)) {
+#if !defined(CONFIG_AM33XX) && !defined(CONFIG_TI81XX)
+		if ((omap_hw_init_context() ==
+				      OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL)) {
+			gd->arch.omap_boot_params.omap_bootmode =
+			*((u8 *)(rom_params + BOOT_MODE_OFFSET));
+		} else
+#endif
+		{
+			dev_desc = *((u32 *)(rom_params + DEV_DESC_PTR_OFFSET));
+			dev_data = *((u32 *)(dev_desc + DEV_DATA_PTR_OFFSET));
+			gd->arch.omap_boot_params.omap_bootmode =
+					*((u32 *)(dev_data + BOOT_MODE_OFFSET));
+		}
+	}
+}
+
 #ifdef CONFIG_SPL_BUILD
 u32 spl_boot_device(void)
 {
diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
index 1645120..0776d5c 100644
--- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c
+++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c
@@ -84,7 +84,7 @@
 	return rev;
 }
 
-void omap_rev_string(void)
+static void omap_rev_string(void)
 {
 	u32 omap_rev = omap_revision();
 	u32 soc_variant	= (omap_rev & 0xF0000000) >> 28;
@@ -111,42 +111,6 @@
 {
 }
 
-static void save_omap_boot_params(void)
-{
-	u32 rom_params = *((u32 *)OMAP_SRAM_SCRATCH_BOOT_PARAMS);
-	u8 boot_device;
-	u32 dev_desc, dev_data;
-
-	if ((rom_params <  NON_SECURE_SRAM_START) ||
-	    (rom_params > NON_SECURE_SRAM_END))
-		return;
-
-	/*
-	 * rom_params can be type casted to omap_boot_parameters and
-	 * used. But it not correct to assume that romcode structure
-	 * encoding would be same as u-boot. So use the defined offsets.
-	 */
-	gd->arch.omap_boot_params.omap_bootdevice = boot_device =
-				   *((u8 *)(rom_params + BOOT_DEVICE_OFFSET));
-
-	gd->arch.omap_boot_params.ch_flags =
-				*((u8 *)(rom_params + CH_FLAGS_OFFSET));
-
-	if ((boot_device >= MMC_BOOT_DEVICES_START) &&
-	    (boot_device <= MMC_BOOT_DEVICES_END)) {
-		if ((omap_hw_init_context() ==
-				      OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL)) {
-			gd->arch.omap_boot_params.omap_bootmode =
-			*((u8 *)(rom_params + BOOT_MODE_OFFSET));
-		} else {
-			dev_desc = *((u32 *)(rom_params + DEV_DESC_PTR_OFFSET));
-			dev_data = *((u32 *)(dev_desc + DEV_DATA_PTR_OFFSET));
-			gd->arch.omap_boot_params.omap_bootmode =
-					*((u32 *)(dev_data + BOOT_MODE_OFFSET));
-		}
-	}
-}
-
 #ifdef CONFIG_ARCH_CPU_INIT
 /*
  * SOC specific cpu init
diff --git a/arch/arm/include/asm/arch-am33xx/omap.h b/arch/arm/include/asm/arch-am33xx/omap.h
index 7e3bb9c..e7576c1 100644
--- a/arch/arm/include/asm/arch-am33xx/omap.h
+++ b/arch/arm/include/asm/arch-am33xx/omap.h
@@ -29,10 +29,12 @@
  * at 0x40304000(EMU base) so that our code works for both EMU and GP
  */
 #ifdef CONFIG_AM33XX
-#define NON_SECURE_SRAM_START	0x40304000
-#define NON_SECURE_SRAM_END	0x4030E000
+#define NON_SECURE_SRAM_START	0x402F0400
+#define NON_SECURE_SRAM_END	0x40310000
+#define SRAM_SCRATCH_SPACE_ADDR	0x4030C000
 #elif defined(CONFIG_TI814X)
 #define NON_SECURE_SRAM_START	0x40300000
 #define NON_SECURE_SRAM_END	0x40320000
+#define SRAM_SCRATCH_SPACE_ADDR	0x4031B800
 #endif
 #endif
diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
index c913b5f..fedc674 100644
--- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
@@ -30,6 +30,7 @@
 
 extern struct ctrl_stat *cstat;
 u32 get_device_type(void);
+void save_omap_boot_params(void);
 void setup_clocks_for_console(void);
 void ddr_pll_config(unsigned int ddrpll_M);
 
diff --git a/arch/arm/include/asm/arch-omap4/omap.h b/arch/arm/include/asm/arch-omap4/omap.h
index e9a6ffe..44353a4 100644
--- a/arch/arm/include/asm/arch-omap4/omap.h
+++ b/arch/arm/include/asm/arch-omap4/omap.h
@@ -141,6 +141,7 @@
  */
 #define NON_SECURE_SRAM_START	0x40304000
 #define NON_SECURE_SRAM_END	0x4030E000	/* Not inclusive */
+#define SRAM_SCRATCH_SPACE_ADDR	NON_SECURE_SRAM_START
 /* base address for indirect vectors (internal boot mode) */
 #define SRAM_ROM_VECT_BASE	0x4030D000
 #endif
diff --git a/arch/arm/include/asm/arch-omap4/sys_proto.h b/arch/arm/include/asm/arch-omap4/sys_proto.h
index 039a1f2..ef85594 100644
--- a/arch/arm/include/asm/arch-omap4/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap4/sys_proto.h
@@ -54,6 +54,7 @@
 void sdram_init(void);
 u32 omap_sdram_size(void);
 u32 cortex_rev(void);
+void save_omap_boot_params(void);
 void init_omap_revision(void);
 void do_io_settings(void);
 void omap_vc_init(u16 speed_khz);
diff --git a/arch/arm/include/asm/arch-omap5/omap.h b/arch/arm/include/asm/arch-omap5/omap.h
index 4f43a90..04af227 100644
--- a/arch/arm/include/asm/arch-omap5/omap.h
+++ b/arch/arm/include/asm/arch-omap5/omap.h
@@ -188,6 +188,7 @@
  */
 #define NON_SECURE_SRAM_START	0x40300000
 #define NON_SECURE_SRAM_END	0x40320000	/* Not inclusive */
+#define SRAM_SCRATCH_SPACE_ADDR	NON_SECURE_SRAM_START
 /* base address for indirect vectors (internal boot mode) */
 #define SRAM_ROM_VECT_BASE	0x4031F000
 
diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h
index b79161d..4d99db9 100644
--- a/arch/arm/include/asm/arch-omap5/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap5/sys_proto.h
@@ -58,6 +58,7 @@
 void sdram_init(void);
 u32 omap_sdram_size(void);
 u32 cortex_rev(void);
+void save_omap_boot_params(void);
 void init_omap_revision(void);
 void do_io_settings(void);
 void omap_vc_init(u16 speed_khz);
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index ee7b188..baeef4e 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -591,7 +591,6 @@
 /*
  * SRAM scratch space entries
  */
-#define SRAM_SCRATCH_SPACE_ADDR		NON_SECURE_SRAM_START
 #define OMAP_SRAM_SCRATCH_OMAP_REV	SRAM_SCRATCH_SPACE_ADDR
 #define OMAP_SRAM_SCRATCH_EMIF_SIZE	(SRAM_SCRATCH_SPACE_ADDR + 0x4)
 #define OMAP_SRAM_SCRATCH_EMIF_T_NUM	(SRAM_SCRATCH_SPACE_ADDR + 0xC)
diff --git a/board/isee/igep0033/board.c b/board/isee/igep0033/board.c
index d315516..826cead 100644
--- a/board/isee/igep0033/board.c
+++ b/board/isee/igep0033/board.c
@@ -105,6 +105,15 @@
  */
 void s_init(void)
 {
+	/*
+	 * Save the boot parameters passed from romcode.
+	 * We cannot delay the saving further than this,
+	 * to prevent overwrites.
+	 */
+#ifdef CONFIG_SPL_BUILD
+	save_omap_boot_params();
+#endif
+
 	/* WDT1 is already running when the bootloader gets control
 	 * Disable it to avoid "random" resets
 	 */
diff --git a/board/phytec/pcm051/board.c b/board/phytec/pcm051/board.c
index 43d7b6e..93c611d 100644
--- a/board/phytec/pcm051/board.c
+++ b/board/phytec/pcm051/board.c
@@ -115,6 +115,15 @@
 void s_init(void)
 {
 	/*
+	 * Save the boot parameters passed from romcode.
+	 * We cannot delay the saving further than this,
+	 * to prevent overwrites.
+	 */
+#ifdef CONFIG_SPL_BUILD
+	save_omap_boot_params();
+#endif
+
+	/*
 	 * WDT1 is already running when the bootloader gets control
 	 * Disable it to avoid "random" resets
 	 */
diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index b371376..ebddf0c 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -304,6 +304,15 @@
  */
 void s_init(void)
 {
+	/*
+	 * Save the boot parameters passed from romcode.
+	 * We cannot delay the saving further than this,
+	 * to prevent overwrites.
+	 */
+#ifdef CONFIG_SPL_BUILD
+	save_omap_boot_params();
+#endif
+
 	/* WDT1 is already running when the bootloader gets control
 	 * Disable it to avoid "random" resets
 	 */
diff --git a/board/ti/ti814x/evm.c b/board/ti/ti814x/evm.c
index 7adb524..4759b16 100644
--- a/board/ti/ti814x/evm.c
+++ b/board/ti/ti814x/evm.c
@@ -149,6 +149,15 @@
 void s_init(void)
 {
 #ifdef CONFIG_SPL_BUILD
+	/*
+	 * Save the boot parameters passed from romcode.
+	 * We cannot delay the saving further than this,
+	 * to prevent overwrites.
+	 */
+#ifdef CONFIG_SPL_BUILD
+	save_omap_boot_params();
+#endif
+
 	/* WDT1 is already running when the bootloader gets control
 	 * Disable it to avoid "random" resets
 	 */
diff --git a/common/board_f.c b/common/board_f.c
index 81edbdf..9fa7363 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -851,12 +851,6 @@
 #ifdef CONFIG_ARM
 	timer_init,		/* initialize timer */
 #endif
-#ifdef CONFIG_BOARD_POSTCLK_INIT
-	board_postclk_init,
-#endif
-#ifdef CONFIG_FSL_ESDHC
-	get_clocks,
-#endif
 #ifdef CONFIG_SYS_ALLOC_DPRAM
 #if !defined(CONFIG_CPM2)
 	dpram_init,
@@ -865,6 +859,9 @@
 #if defined(CONFIG_BOARD_POSTCLK_INIT)
 	board_postclk_init,
 #endif
+#ifdef CONFIG_FSL_ESDHC
+	get_clocks,
+#endif
 	env_init,		/* initialize environment */
 #if defined(CONFIG_8xx_CPUCLK_DEFAULT)
 	/* get CPU and bus clocks according to the environment variable */
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 15f4599..05130b6 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -93,11 +93,6 @@
 static void fixup_silent_linux(void);
 #endif
 
-static image_header_t *image_get_kernel(ulong img_addr, int verify);
-#if defined(CONFIG_FIT)
-static int fit_check_kernel(const void *fit, int os_noffset, int verify);
-#endif
-
 static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 				char * const argv[], bootm_headers_t *images,
 				ulong *os_data, ulong *os_len);
@@ -306,7 +301,7 @@
 
 #if defined(CONFIG_OF_LIBFDT)
 		/* find flattened device tree */
-		ret = boot_get_fdt(flag, argc, argv, &images,
+		ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images,
 				   &images.ft_addr, &images.ft_len);
 		if (ret) {
 			puts("Could not find a valid device tree\n");
@@ -336,12 +331,15 @@
 	ulong image_len = os.image_len;
 	__maybe_unused uint unc_len = CONFIG_SYS_BOOTM_LEN;
 	int no_overlap = 0;
+	void *load_buf, *image_buf;
 #if defined(CONFIG_LZMA) || defined(CONFIG_LZO)
 	int ret;
 #endif /* defined(CONFIG_LZMA) || defined(CONFIG_LZO) */
 
 	const char *type_name = genimg_get_type_name(os.type);
 
+	load_buf = map_sysmem(load, image_len);
+	image_buf = map_sysmem(image_start, image_len);
 	switch (comp) {
 	case IH_COMP_NONE:
 		if (load == blob_start || load == image_start) {
@@ -349,8 +347,7 @@
 			no_overlap = 1;
 		} else {
 			printf("   Loading %s ... ", type_name);
-			memmove_wd((void *)load, (void *)image_start,
-					image_len, CHUNKSZ);
+			memmove_wd(load_buf, image_buf, image_len, CHUNKSZ);
 		}
 		*load_end = load + image_len;
 		puts("OK\n");
@@ -358,8 +355,7 @@
 #ifdef CONFIG_GZIP
 	case IH_COMP_GZIP:
 		printf("   Uncompressing %s ... ", type_name);
-		if (gunzip((void *)load, unc_len,
-				(uchar *)image_start, &image_len) != 0) {
+		if (gunzip(load_buf, unc_len, image_buf, &image_len) != 0) {
 			puts("GUNZIP: uncompress, out-of-mem or overwrite "
 				"error - must RESET board to recover\n");
 			if (boot_progress)
@@ -378,9 +374,9 @@
 		 * use slower decompression algorithm which requires
 		 * at most 2300 KB of memory.
 		 */
-		int i = BZ2_bzBuffToBuffDecompress((char *)load,
-					&unc_len, (char *)image_start, image_len,
-					CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
+		int i = BZ2_bzBuffToBuffDecompress(load_buf, &unc_len,
+			image_buf, image_len,
+			CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0);
 		if (i != BZ_OK) {
 			printf("BUNZIP2: uncompress or overwrite error %d "
 				"- must RESET board to recover\n", i);
@@ -397,9 +393,8 @@
 		SizeT lzma_len = unc_len;
 		printf("   Uncompressing %s ... ", type_name);
 
-		ret = lzmaBuffToBuffDecompress(
-			(unsigned char *)load, &lzma_len,
-			(unsigned char *)image_start, image_len);
+		ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len,
+					       image_buf, image_len);
 		unc_len = lzma_len;
 		if (ret != SZ_OK) {
 			printf("LZMA: uncompress or overwrite error %d "
@@ -415,9 +410,8 @@
 	case IH_COMP_LZO:
 		printf("   Uncompressing %s ... ", type_name);
 
-		ret = lzop_decompress((const unsigned char *)image_start,
-					  image_len, (unsigned char *)load,
-					  &unc_len);
+		ret = lzop_decompress(image_buf, image_len, load_buf,
+				      &unc_len);
 		if (ret != LZO_E_OK) {
 			printf("LZO: uncompress or overwrite error %d "
 			      "- must RESET board to recover\n", ret);
@@ -795,54 +789,6 @@
 	}
 	return hdr;
 }
-
-/**
- * fit_check_kernel - verify FIT format kernel subimage
- * @fit_hdr: pointer to the FIT image header
- * os_noffset: kernel subimage node offset within FIT image
- * @verify: data CRC verification flag
- *
- * fit_check_kernel() verifies integrity of the kernel subimage and from
- * specified FIT image.
- *
- * returns:
- *     1, on success
- *     0, on failure
- */
-#if defined(CONFIG_FIT)
-static int fit_check_kernel(const void *fit, int os_noffset, int verify)
-{
-	fit_image_print(fit, os_noffset, "   ");
-
-	if (verify) {
-		puts("   Verifying Hash Integrity ... ");
-		if (!fit_image_verify(fit, os_noffset)) {
-			puts("Bad Data Hash\n");
-			bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH);
-			return 0;
-		}
-		puts("OK\n");
-	}
-	bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_ARCH);
-
-	if (!fit_image_check_target_arch(fit, os_noffset)) {
-		puts("Unsupported Architecture\n");
-		bootstage_error(BOOTSTAGE_ID_FIT_CHECK_ARCH);
-		return 0;
-	}
-
-	bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_KERNEL);
-	if (!fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL) &&
-	    !fit_image_check_type(fit, os_noffset, IH_TYPE_KERNEL_NOLOAD)) {
-		puts("Not a kernel image\n");
-		bootstage_error(BOOTSTAGE_ID_FIT_CHECK_KERNEL);
-		return 0;
-	}
-
-	bootstage_mark(BOOTSTAGE_ID_FIT_CHECKED);
-	return 1;
-}
-#endif /* CONFIG_FIT */
 
 /**
  * boot_get_kernel - find kernel image
@@ -864,12 +810,8 @@
 	ulong		img_addr;
 	const void *buf;
 #if defined(CONFIG_FIT)
-	const void	*fit_hdr;
 	const char	*fit_uname_config = NULL;
 	const char	*fit_uname_kernel = NULL;
-	const void	*data;
-	size_t		len;
-	int		cfg_noffset;
 	int		os_noffset;
 #endif
 
@@ -946,84 +888,16 @@
 		break;
 #if defined(CONFIG_FIT)
 	case IMAGE_FORMAT_FIT:
-		fit_hdr = buf;
-		printf("## Booting kernel from FIT Image at %08lx ...\n",
-				img_addr);
-
-		if (!fit_check_format(fit_hdr)) {
-			puts("Bad FIT kernel image format!\n");
-			bootstage_error(BOOTSTAGE_ID_FIT_FORMAT);
-			return NULL;
-		}
-		bootstage_mark(BOOTSTAGE_ID_FIT_FORMAT);
-
-		if (!fit_uname_kernel) {
-			/*
-			 * no kernel image node unit name, try to get config
-			 * node first. If config unit node name is NULL
-			 * fit_conf_get_node() will try to find default config
-			 * node
-			 */
-			bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
-#ifdef CONFIG_FIT_BEST_MATCH
-			if (fit_uname_config)
-				cfg_noffset =
-					fit_conf_get_node(fit_hdr,
-							  fit_uname_config);
-			else
-				cfg_noffset =
-					fit_conf_find_compat(fit_hdr,
-							     gd->fdt_blob);
-#else
-			cfg_noffset = fit_conf_get_node(fit_hdr,
-							fit_uname_config);
-#endif
-			if (cfg_noffset < 0) {
-				bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
-				return NULL;
-			}
-			/* save configuration uname provided in the first
-			 * bootm argument
-			 */
-			images->fit_uname_cfg = fdt_get_name(fit_hdr,
-								cfg_noffset,
-								NULL);
-			printf("   Using '%s' configuration\n",
-				images->fit_uname_cfg);
-			bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
-
-			os_noffset = fit_conf_get_kernel_node(fit_hdr,
-								cfg_noffset);
-			fit_uname_kernel = fit_get_name(fit_hdr, os_noffset,
-							NULL);
-		} else {
-			/* get kernel component image node offset */
-			bootstage_mark(BOOTSTAGE_ID_FIT_UNIT_NAME);
-			os_noffset = fit_image_get_node(fit_hdr,
-							fit_uname_kernel);
-		}
-		if (os_noffset < 0) {
-			bootstage_error(BOOTSTAGE_ID_FIT_CONFIG);
-			return NULL;
-		}
-
-		printf("   Trying '%s' kernel subimage\n", fit_uname_kernel);
-
-		bootstage_mark(BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE);
-		if (!fit_check_kernel(fit_hdr, os_noffset, images->verify))
+		os_noffset = fit_image_load(images, FIT_KERNEL_PROP,
+				img_addr,
+				&fit_uname_kernel, fit_uname_config,
+				IH_ARCH_DEFAULT, IH_TYPE_KERNEL,
+				BOOTSTAGE_ID_FIT_KERNEL_START,
+				FIT_LOAD_IGNORED, os_data, os_len);
+		if (os_noffset < 0)
 			return NULL;
 
-		/* get kernel image data address and length */
-		if (fit_image_get_data(fit_hdr, os_noffset, &data, &len)) {
-			puts("Could not find kernel subimage data!\n");
-			bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR);
-			return NULL;
-		}
-		bootstage_mark(BOOTSTAGE_ID_FIT_KERNEL_INFO);
-
-		*os_len = len;
-		*os_data = (ulong)data;
-		images->fit_hdr_os = (void *)fit_hdr;
+		images->fit_hdr_os = map_sysmem(img_addr, 0);
 		images->fit_uname_os = fit_uname_kernel;
 		images->fit_noffset_os = os_noffset;
 		break;
@@ -1820,7 +1694,7 @@
 
 #if defined(CONFIG_OF_LIBFDT)
 	/* find flattened device tree */
-	ret = boot_get_fdt(flag, argc, argv, images,
+	ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
 			   &images->ft_addr, &images->ft_len);
 	if (ret) {
 		puts("Could not find a valid device tree\n");
diff --git a/common/cmd_fitupd.c b/common/cmd_fitupd.c
index 7a3789e..618ff7c 100644
--- a/common/cmd_fitupd.c
+++ b/common/cmd_fitupd.c
@@ -8,13 +8,12 @@
 
 #include <common.h>
 #include <command.h>
+#include <net.h>
 
 #if !defined(CONFIG_UPDATE_TFTP)
 #error "CONFIG_UPDATE_TFTP required"
 #endif
 
-extern int update_tftp(ulong addr);
-
 static int do_fitupd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	ulong addr = 0UL;
diff --git a/common/image-fdt.c b/common/image-fdt.c
index 158c9cf..0d421d9 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -211,51 +211,11 @@
 	return 1;
 }
 
-#if defined(CONFIG_FIT)
-/**
- * fit_check_fdt - verify FIT format FDT subimage
- * @fit_hdr: pointer to the FIT  header
- * fdt_noffset: FDT subimage node offset within FIT image
- * @verify: data CRC verification flag
- *
- * fit_check_fdt() verifies integrity of the FDT subimage and from
- * specified FIT image.
- *
- * returns:
- *     1, on success
- *     0, on failure
- */
-static int fit_check_fdt(const void *fit, int fdt_noffset, int verify)
-{
-	fit_image_print(fit, fdt_noffset, "   ");
-
-	if (verify) {
-		puts("   Verifying Hash Integrity ... ");
-		if (!fit_image_verify(fit, fdt_noffset)) {
-			fdt_error("Bad Data Hash");
-			return 0;
-		}
-		puts("OK\n");
-	}
-
-	if (!fit_image_check_type(fit, fdt_noffset, IH_TYPE_FLATDT)) {
-		fdt_error("Not a FDT image");
-		return 0;
-	}
-
-	if (!fit_image_check_comp(fit, fdt_noffset, IH_COMP_NONE)) {
-		fdt_error("FDT image is compressed");
-		return 0;
-	}
-
-	return 1;
-}
-#endif
-
 /**
  * boot_get_fdt - main fdt handling routine
  * @argc: command argument count
  * @argv: command argument list
+ * @arch: architecture (IH_ARCH_...)
  * @images: pointer to the bootm images structure
  * @of_flat_tree: pointer to a char* variable, will hold fdt start address
  * @of_size: pointer to a ulong variable, will hold fdt length
@@ -273,24 +233,20 @@
  *     1, if fdt image is found but corrupted
  *     of_flat_tree and of_size are set to 0 if no fdt exists
  */
-int boot_get_fdt(int flag, int argc, char * const argv[],
+int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
 		bootm_headers_t *images, char **of_flat_tree, ulong *of_size)
 {
 	const image_header_t *fdt_hdr;
 	ulong		fdt_addr;
 	char		*fdt_blob = NULL;
 	ulong		image_start, image_data, image_end;
-	ulong		load_start, load_end;
+	ulong		load, load_end;
 	void		*buf;
 #if defined(CONFIG_FIT)
-	void		*fit_hdr;
 	const char	*fit_uname_config = NULL;
 	const char	*fit_uname_fdt = NULL;
 	ulong		default_addr;
-	int		cfg_noffset;
 	int		fdt_noffset;
-	const void	*data;
-	size_t		size;
 #endif
 
 	*of_flat_tree = NULL;
@@ -333,31 +289,15 @@
 			 * command argument
 			 */
 			fdt_addr = map_to_sysmem(images->fit_hdr_os);
-			fit_uname_config = images->fit_uname_cfg;
-			debug("*  fdt: using config '%s' from image at 0x%08lx\n",
-			      fit_uname_config, fdt_addr);
-
-			/*
-			 * Check whether configuration has FDT blob defined,
-			 * if not quit silently.
-			 */
-			fit_hdr = images->fit_hdr_os;
-			cfg_noffset = fit_conf_get_node(fit_hdr,
-					fit_uname_config);
-			if (cfg_noffset < 0) {
-				debug("*  fdt: no such config\n");
+			fdt_noffset = fit_get_node_from_config(images,
+							       FIT_FDT_PROP,
+							       fdt_addr);
+			if (fdt_noffset == -ENOLINK)
 				return 0;
-			}
-
-			fdt_noffset = fit_conf_get_fdt_node(fit_hdr,
-					cfg_noffset);
-			if (fdt_noffset < 0) {
-				debug("*  fdt: no fdt in config\n");
-				return 0;
-			}
+			else if (fdt_noffset < 0)
+				return 1;
 		}
 #endif
-
 		debug("## Checking for 'FDT'/'FDT Image' at %08lx\n",
 		      fdt_addr);
 
@@ -387,29 +327,28 @@
 			image_data = (ulong)image_get_data(fdt_hdr);
 			image_end = image_get_image_end(fdt_hdr);
 
-			load_start = image_get_load(fdt_hdr);
-			load_end = load_start + image_get_data_size(fdt_hdr);
+			load = image_get_load(fdt_hdr);
+			load_end = load + image_get_data_size(fdt_hdr);
 
-			if (load_start == image_start ||
-			    load_start == image_data) {
+			if (load == image_start ||
+			    load == image_data) {
 				fdt_blob = (char *)image_data;
 				break;
 			}
 
-			if ((load_start < image_end) &&
-			    (load_end > image_start)) {
+			if ((load < image_end) && (load_end > image_start)) {
 				fdt_error("fdt overwritten");
 				goto error;
 			}
 
 			debug("   Loading FDT from 0x%08lx to 0x%08lx\n",
-			      image_data, load_start);
+			      image_data, load);
 
-			memmove((void *)load_start,
+			memmove((void *)load,
 				(void *)image_data,
 				image_get_data_size(fdt_hdr));
 
-			fdt_blob = (char *)load_start;
+			fdt_addr = load;
 			break;
 		case IMAGE_FORMAT_FIT:
 			/*
@@ -420,107 +359,20 @@
 #if defined(CONFIG_FIT)
 			/* check FDT blob vs FIT blob */
 			if (fit_check_format(buf)) {
-				/*
-				 * FIT image
-				 */
-				fit_hdr = buf;
-				printf("## Flattened Device Tree from FIT Image at %08lx\n",
-				       fdt_addr);
+				ulong load, len;
 
-				if (!fit_uname_fdt) {
-					/*
-					 * no FDT blob image node unit name,
-					 * try to get config node first. If
-					 * config unit node name is NULL
-					 * fit_conf_get_node() will try to
-					 * find default config node
-					 */
-					cfg_noffset = fit_conf_get_node(fit_hdr,
-							fit_uname_config);
+				fdt_noffset = fit_image_load(images,
+					FIT_FDT_PROP,
+					fdt_addr, &fit_uname_fdt,
+					fit_uname_config,
+					arch, IH_TYPE_FLATDT,
+					BOOTSTAGE_ID_FIT_FDT_START,
+					FIT_LOAD_OPTIONAL, &load, &len);
 
-					if (cfg_noffset < 0) {
-						fdt_error("Could not find configuration node\n");
-						goto error;
-					}
-
-					fit_uname_config = fdt_get_name(fit_hdr,
-							cfg_noffset, NULL);
-					printf("   Using '%s' configuration\n",
-					       fit_uname_config);
-
-					fdt_noffset = fit_conf_get_fdt_node(
-							fit_hdr,
-							cfg_noffset);
-					fit_uname_fdt = fit_get_name(fit_hdr,
-							fdt_noffset, NULL);
-				} else {
-					/*
-					 * get FDT component image node
-					 * offset
-					 */
-					fdt_noffset = fit_image_get_node(
-								fit_hdr,
-								fit_uname_fdt);
-				}
-				if (fdt_noffset < 0) {
-					fdt_error("Could not find subimage node\n");
-					goto error;
-				}
-
-				printf("   Trying '%s' FDT blob subimage\n",
-				       fit_uname_fdt);
-
-				if (!fit_check_fdt(fit_hdr, fdt_noffset,
-						   images->verify))
-					goto error;
-
-				/* get ramdisk image data address and length */
-				if (fit_image_get_data(fit_hdr, fdt_noffset,
-						       &data, &size)) {
-					fdt_error("Could not find FDT subimage data");
-					goto error;
-				}
-
-				/*
-				 * verify that image data is a proper FDT
-				 * blob
-				 */
-				if (fdt_check_header((char *)data) != 0) {
-					fdt_error("Subimage data is not a FTD");
-					goto error;
-				}
-
-				/*
-				 * move image data to the load address,
-				 * make sure we don't overwrite initial image
-				 */
-				image_start = (ulong)fit_hdr;
-				image_end = fit_get_end(fit_hdr);
-
-				if (fit_image_get_load(fit_hdr, fdt_noffset,
-						       &load_start) == 0) {
-					load_end = load_start + size;
-
-					if ((load_start < image_end) &&
-					    (load_end > image_start)) {
-						fdt_error("FDT overwritten");
-						goto error;
-					}
-
-					printf("   Loading FDT from 0x%08lx to 0x%08lx\n",
-					       (ulong)data, load_start);
-
-					memmove((void *)load_start,
-						(void *)data, size);
-
-					fdt_blob = (char *)load_start;
-				} else {
-					fdt_blob = (char *)data;
-				}
-
-				images->fit_hdr_fdt = fit_hdr;
+				images->fit_hdr_fdt = map_sysmem(fdt_addr, 0);
 				images->fit_uname_fdt = fit_uname_fdt;
 				images->fit_noffset_fdt = fdt_noffset;
+				fdt_addr = load;
 				break;
 			} else
 #endif
@@ -528,7 +380,6 @@
 				/*
 				 * FDT blob
 				 */
-				fdt_blob = buf;
 				debug("*  fdt: raw FDT blob\n");
 				printf("## Flattened Device Tree blob at %08lx\n",
 				       (long)fdt_addr);
@@ -539,8 +390,8 @@
 			goto error;
 		}
 
-		printf("   Booting using the fdt blob at 0x%p\n", fdt_blob);
-
+		printf("   Booting using the fdt blob at %#08lx\n", fdt_addr);
+		fdt_blob = map_sysmem(fdt_addr, 0);
 	} else if (images->legacy_hdr_valid &&
 			image_check_type(&images->legacy_hdr_os_copy,
 					 IH_TYPE_MULTI)) {
diff --git a/common/image-fit.c b/common/image-fit.c
index 254feec..7bf82d3 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -31,6 +31,9 @@
 #include <time.h>
 #else
 #include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 
 #include <bootstage.h>
@@ -348,10 +351,13 @@
 
 #ifndef USE_HOSTCC
 	printf("%s  Data Start:   ", p);
-	if (ret)
+	if (ret) {
 		printf("unavailable\n");
-	else
-		printf("0x%08lx\n", (ulong)data);
+	} else {
+		void *vdata = (void *)data;
+
+		printf("0x%08lx\n", (ulong)map_to_sysmem(vdata));
+	}
 #endif
 
 	printf("%s  Data Size:    ", p);
@@ -1349,63 +1355,6 @@
 }
 
 /**
- * fit_conf_get_kernel_node - get kernel image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_kernel_node() retrives kernel image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_kernel_node(const void *fit, int noffset)
-{
-	return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP);
-}
-
-/**
- * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_ramdisk_node(const void *fit, int noffset)
-{
-	return fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP);
-}
-
-/**
- * fit_conf_get_fdt_node - get fdt image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_fdt_node() retrives fdt image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_fdt_node(const void *fit, int noffset)
-{
-	return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP);
-}
-
-/**
  * fit_conf_print - prints out the FIT configuration details
  * @fit: pointer to the FIT format image header
  * @noffset: offset of the configuration node
@@ -1448,22 +1397,7 @@
 		printf("%s  FDT:          %s\n", p, uname);
 }
 
-/**
- * fit_check_ramdisk - verify FIT format ramdisk subimage
- * @fit_hdr: pointer to the FIT ramdisk header
- * @rd_noffset: ramdisk subimage node offset within FIT image
- * @arch: requested ramdisk image architecture type
- * @verify: data CRC verification flag
- *
- * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from
- * specified FIT image.
- *
- * returns:
- *     1, on success
- *     0, on failure
- */
-int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
-			int verify)
+int fit_image_select(const void *fit, int rd_noffset, int verify)
 {
 	fit_image_print(fit, rd_noffset, "   ");
 
@@ -1471,22 +1405,222 @@
 		puts("   Verifying Hash Integrity ... ");
 		if (!fit_image_verify(fit, rd_noffset)) {
 			puts("Bad Data Hash\n");
-			bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH);
-			return 0;
+			return -EACCES;
 		}
 		puts("OK\n");
 	}
 
-	bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
-	if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) ||
-	    !fit_image_check_arch(fit, rd_noffset, arch) ||
-	    !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) {
-		printf("No Linux %s Ramdisk Image\n",
-		       genimg_get_arch_name(arch));
-		bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
-		return 0;
+	return 0;
+}
+
+int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name,
+			ulong addr)
+{
+	int cfg_noffset;
+	void *fit_hdr;
+	int noffset;
+
+	debug("*  %s: using config '%s' from image at 0x%08lx\n",
+	      prop_name, images->fit_uname_cfg, addr);
+
+	/* Check whether configuration has this property defined */
+	fit_hdr = map_sysmem(addr, 0);
+	cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg);
+	if (cfg_noffset < 0) {
+		debug("*  %s: no such config\n", prop_name);
+		return -ENOENT;
 	}
 
-	bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK);
-	return 1;
+	noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name);
+	if (noffset < 0) {
+		debug("*  %s: no '%s' in config\n", prop_name, prop_name);
+		return -ENOLINK;
+	}
+
+	return noffset;
+}
+
+int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr,
+		   const char **fit_unamep, const char *fit_uname_config,
+		   int arch, int image_type, int bootstage_id,
+		   enum fit_load_op load_op, ulong *datap, ulong *lenp)
+{
+	int cfg_noffset, noffset;
+	const char *fit_uname;
+	const void *fit;
+	const void *buf;
+	size_t size;
+	int type_ok, os_ok;
+	ulong load, data, len;
+	int ret;
+
+	fit = map_sysmem(addr, 0);
+	fit_uname = fit_unamep ? *fit_unamep : NULL;
+	printf("## Loading %s from FIT Image at %08lx ...\n", prop_name, addr);
+
+	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT);
+	if (!fit_check_format(fit)) {
+		printf("Bad FIT %s image format!\n", prop_name);
+		bootstage_error(bootstage_id + BOOTSTAGE_SUB_FORMAT);
+		return -ENOEXEC;
+	}
+	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_FORMAT_OK);
+	if (fit_uname) {
+		/* get ramdisk component image node offset */
+		bootstage_mark(bootstage_id + BOOTSTAGE_SUB_UNIT_NAME);
+		noffset = fit_image_get_node(fit, fit_uname);
+	} else {
+		/*
+		 * no image node unit name, try to get config
+		 * node first. If config unit node name is NULL
+		 * fit_conf_get_node() will try to find default config node
+		 */
+		bootstage_mark(bootstage_id + BOOTSTAGE_SUB_NO_UNIT_NAME);
+		if (IMAGE_ENABLE_BEST_MATCH && !fit_uname_config) {
+			cfg_noffset = fit_conf_find_compat(fit, gd_fdt_blob());
+		} else {
+			cfg_noffset = fit_conf_get_node(fit,
+							fit_uname_config);
+		}
+		if (cfg_noffset < 0) {
+			puts("Could not find configuration node\n");
+			bootstage_error(bootstage_id +
+					BOOTSTAGE_SUB_NO_UNIT_NAME);
+			return -ENOENT;
+		}
+		fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL);
+		printf("   Using '%s' configuration\n", fit_uname_config);
+		if (image_type == IH_TYPE_KERNEL) {
+			/* Remember (and possibly verify) this config */
+			images->fit_uname_cfg = fit_uname_config;
+			if (IMAGE_ENABLE_VERIFY && images->verify) {
+				puts("   Verifying Hash Integrity ... ");
+				if (!fit_config_verify(fit, cfg_noffset)) {
+					puts("Bad Data Hash\n");
+					bootstage_error(bootstage_id +
+						BOOTSTAGE_SUB_HASH);
+					return -EACCES;
+				}
+				puts("OK\n");
+			}
+			bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
+		}
+
+		noffset = fit_conf_get_prop_node(fit, cfg_noffset,
+						 prop_name);
+		fit_uname = fit_get_name(fit, noffset, NULL);
+	}
+	if (noffset < 0) {
+		puts("Could not find subimage node\n");
+		bootstage_error(bootstage_id + BOOTSTAGE_SUB_SUBNODE);
+		return -ENOENT;
+	}
+
+	printf("   Trying '%s' %s subimage\n", fit_uname, prop_name);
+
+	ret = fit_image_select(fit, noffset, images->verify);
+	if (ret) {
+		bootstage_error(bootstage_id + BOOTSTAGE_SUB_HASH);
+		return ret;
+	}
+
+	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
+	if (!fit_image_check_target_arch(fit, noffset)) {
+		puts("Unsupported Architecture\n");
+		bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ARCH);
+		return -ENOEXEC;
+	}
+
+	if (image_type == IH_TYPE_FLATDT &&
+	    !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) {
+		puts("FDT image is compressed");
+		return -EPROTONOSUPPORT;
+	}
+
+	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
+	type_ok = fit_image_check_type(fit, noffset, image_type) ||
+		(image_type == IH_TYPE_KERNEL &&
+			fit_image_check_type(fit, noffset,
+					     IH_TYPE_KERNEL_NOLOAD));
+	os_ok = image_type == IH_TYPE_FLATDT ||
+		fit_image_check_os(fit, noffset, IH_OS_LINUX);
+	if (!type_ok || !os_ok) {
+		printf("No Linux %s %s Image\n", genimg_get_arch_name(arch),
+		       genimg_get_type_name(image_type));
+		bootstage_error(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL);
+		return -EIO;
+	}
+
+	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK);
+
+	/* get image data address and length */
+	if (fit_image_get_data(fit, noffset, &buf, &size)) {
+		printf("Could not find %s subimage data!\n", prop_name);
+		bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA);
+		return -ENOMEDIUM;
+	}
+	len = (ulong)size;
+
+	/* verify that image data is a proper FDT blob */
+	if (image_type == IH_TYPE_FLATDT && fdt_check_header((char *)buf)) {
+		puts("Subimage data is not a FDT");
+		return -ENOEXEC;
+	}
+
+	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK);
+
+	/*
+	 * Work-around for eldk-4.2 which gives this warning if we try to
+	 * case in the unmap_sysmem() call:
+	 * warning: initialization discards qualifiers from pointer target type
+	 */
+	{
+		void *vbuf = (void *)buf;
+
+		data = map_to_sysmem(vbuf);
+	}
+
+	if (load_op == FIT_LOAD_IGNORED) {
+		/* Don't load */
+	} else if (fit_image_get_load(fit, noffset, &load)) {
+		if (load_op == FIT_LOAD_REQUIRED) {
+			printf("Can't get %s subimage load address!\n",
+			       prop_name);
+			bootstage_error(bootstage_id + BOOTSTAGE_SUB_LOAD);
+			return -EBADF;
+		}
+	} else {
+		ulong image_start, image_end;
+		ulong load_end;
+		void *dst;
+
+		/*
+		 * move image data to the load address,
+		 * make sure we don't overwrite initial image
+		 */
+		image_start = addr;
+		image_end = addr + fit_get_size(fit);
+
+		load_end = load + len;
+		if (image_type != IH_TYPE_KERNEL &&
+		    load < image_end && load_end > image_start) {
+			printf("Error: %s overwritten\n", prop_name);
+			return -EXDEV;
+		}
+
+		printf("   Loading %s from 0x%08lx to 0x%08lx\n",
+		       prop_name, data, load);
+
+		dst = map_sysmem(load, len);
+		memmove(dst, buf, len);
+		data = load;
+	}
+	bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
+
+	*datap = data;
+	*lenp = len;
+	if (fit_unamep)
+		*fit_unamep = (char *)fit_uname;
+
+	return noffset;
 }
diff --git a/common/image.c b/common/image.c
index e91c89e..f863502 100644
--- a/common/image.c
+++ b/common/image.c
@@ -51,6 +51,7 @@
 
 #include <u-boot/md5.h>
 #include <sha1.h>
+#include <asm/errno.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_CMD_BDI
@@ -810,14 +811,10 @@
 	char *end;
 #endif
 #if defined(CONFIG_FIT)
-	void		*fit_hdr;
 	const char	*fit_uname_config = NULL;
 	const char	*fit_uname_ramdisk = NULL;
 	ulong		default_addr;
 	int		rd_noffset;
-	int		cfg_noffset;
-	const void	*data;
-	size_t		size;
 #endif
 
 	*rd_start = 0;
@@ -865,32 +862,16 @@
 #if defined(CONFIG_FIT)
 		} else {
 			/* use FIT configuration provided in first bootm
-			 * command argument
+			 * command argument. If the property is not defined,
+			 * quit silently.
 			 */
 			rd_addr = map_to_sysmem(images->fit_hdr_os);
-			fit_uname_config = images->fit_uname_cfg;
-			debug("*  ramdisk: using config '%s' from image "
-					"at 0x%08lx\n",
-					fit_uname_config, rd_addr);
-
-			/*
-			 * Check whether configuration has ramdisk defined,
-			 * if not, don't try to use it, quit silently.
-			 */
-			fit_hdr = images->fit_hdr_os;
-			cfg_noffset = fit_conf_get_node(fit_hdr,
-							fit_uname_config);
-			if (cfg_noffset < 0) {
-				debug("*  ramdisk: no such config\n");
-				return 1;
-			}
-
-			rd_noffset = fit_conf_get_ramdisk_node(fit_hdr,
-								cfg_noffset);
-			if (rd_noffset < 0) {
-				debug("*  ramdisk: no ramdisk in config\n");
+			rd_noffset = fit_get_node_from_config(images,
+					FIT_RAMDISK_PROP, rd_addr);
+			if (rd_noffset == -ENOLINK)
 				return 0;
-			}
+			else if (rd_noffset < 0)
+				return 1;
 		}
 #endif
 
@@ -921,87 +902,16 @@
 			break;
 #if defined(CONFIG_FIT)
 		case IMAGE_FORMAT_FIT:
-			fit_hdr = buf;
-			printf("## Loading init Ramdisk from FIT "
-					"Image at %08lx ...\n", rd_addr);
-
-			bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT);
-			if (!fit_check_format(fit_hdr)) {
-				puts("Bad FIT ramdisk image format!\n");
-				bootstage_error(
-					BOOTSTAGE_ID_FIT_RD_FORMAT);
-				return 1;
-			}
-			bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT_OK);
-
-			if (!fit_uname_ramdisk) {
-				/*
-				 * no ramdisk image node unit name, try to get config
-				 * node first. If config unit node name is NULL
-				 * fit_conf_get_node() will try to find default config node
-				 */
-				bootstage_mark(
-					BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME);
-				cfg_noffset = fit_conf_get_node(fit_hdr,
-							fit_uname_config);
-				if (cfg_noffset < 0) {
-					puts("Could not find configuration "
-						"node\n");
-					bootstage_error(
-					BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME);
-					return 1;
-				}
-				fit_uname_config = fdt_get_name(fit_hdr,
-							cfg_noffset, NULL);
-				printf("   Using '%s' configuration\n",
-					fit_uname_config);
-
-				rd_noffset = fit_conf_get_ramdisk_node(fit_hdr,
-							cfg_noffset);
-				fit_uname_ramdisk = fit_get_name(fit_hdr,
-							rd_noffset, NULL);
-			} else {
-				/* get ramdisk component image node offset */
-				bootstage_mark(
-					BOOTSTAGE_ID_FIT_RD_UNIT_NAME);
-				rd_noffset = fit_image_get_node(fit_hdr,
-						fit_uname_ramdisk);
-			}
-			if (rd_noffset < 0) {
-				puts("Could not find subimage node\n");
-				bootstage_error(BOOTSTAGE_ID_FIT_RD_SUBNODE);
-				return 1;
-			}
-
-			printf("   Trying '%s' ramdisk subimage\n",
-				fit_uname_ramdisk);
-
-			bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK);
-			if (!fit_check_ramdisk(fit_hdr, rd_noffset, arch,
-						images->verify))
+			rd_noffset = fit_image_load(images, FIT_RAMDISK_PROP,
+					rd_addr, &fit_uname_ramdisk,
+					fit_uname_config, arch,
+					IH_TYPE_RAMDISK,
+					BOOTSTAGE_ID_FIT_RD_START,
+					FIT_LOAD_REQUIRED, &rd_data, &rd_len);
+			if (rd_noffset < 0)
 				return 1;
 
-			/* get ramdisk image data address and length */
-			if (fit_image_get_data(fit_hdr, rd_noffset, &data,
-						&size)) {
-				puts("Could not find ramdisk subimage data!\n");
-				bootstage_error(BOOTSTAGE_ID_FIT_RD_GET_DATA);
-				return 1;
-			}
-			bootstage_mark(BOOTSTAGE_ID_FIT_RD_GET_DATA_OK);
-
-			rd_data = (ulong)data;
-			rd_len = size;
-
-			if (fit_image_get_load(fit_hdr, rd_noffset, &rd_load)) {
-				puts("Can't get ramdisk subimage load "
-					"address!\n");
-				bootstage_error(BOOTSTAGE_ID_FIT_RD_LOAD);
-				return 1;
-			}
-			bootstage_mark(BOOTSTAGE_ID_FIT_RD_LOAD);
-
-			images->fit_hdr_rd = fit_hdr;
+			images->fit_hdr_rd = map_sysmem(rd_addr, 0);
 			images->fit_uname_rd = fit_uname_ramdisk;
 			images->fit_noffset_rd = rd_noffset;
 			break;
diff --git a/common/main.c b/common/main.c
index 953ef29..56da214 100644
--- a/common/main.c
+++ b/common/main.c
@@ -28,26 +28,15 @@
 /* #define	DEBUG	*/
 
 #include <common.h>
-#include <watchdog.h>
 #include <command.h>
 #include <fdtdec.h>
-#include <malloc.h>
-#include <version.h>
-#ifdef CONFIG_MODEM_SUPPORT
-#include <malloc.h>		/* for free() prototype */
-#endif
-
-#ifdef CONFIG_SYS_HUSH_PARSER
 #include <hush.h>
-#endif
-
-#ifdef CONFIG_OF_CONTROL
-#include <fdtdec.h>
-#endif
-
+#include <malloc.h>
+#include <menu.h>
 #include <post.h>
+#include <version.h>
+#include <watchdog.h>
 #include <linux/ctype.h>
-#include <menu.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -57,13 +46,18 @@
 void inline __show_boot_progress (int val) {}
 void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress")));
 
-#if defined(CONFIG_UPDATE_TFTP)
-int update_tftp (ulong addr);
-#endif /* CONFIG_UPDATE_TFTP */
-
 #define MAX_DELAY_STOP_STR 32
 
-#undef DEBUG_PARSER
+#define DEBUG_PARSER	0	/* set to 1 to debug */
+
+#define debug_parser(fmt, args...)		\
+	debug_cond(DEBUG_PARSER, fmt, ##args)
+
+#ifndef DEBUG_BOOTKEYS
+#define DEBUG_BOOTKEYS 0
+#endif
+#define debug_bootkeys(fmt, args...)		\
+	debug_cond(DEBUG_BOOTKEYS, fmt, ##args)
 
 char        console_buffer[CONFIG_SYS_CBSIZE + 1];	/* console I/O buffer	*/
 
@@ -93,10 +87,7 @@
  */
 #if defined(CONFIG_BOOTDELAY)
 # if defined(CONFIG_AUTOBOOT_KEYED)
-#ifndef CONFIG_MENU
-static inline
-#endif
-int abortboot(int bootdelay)
+static int abortboot_keyed(int bootdelay)
 {
 	int abort = 0;
 	uint64_t etime = endtick(bootdelay);
@@ -152,11 +143,9 @@
 		presskey_max = presskey_max > delaykey[i].len ?
 				    presskey_max : delaykey[i].len;
 
-#  if DEBUG_BOOTKEYS
-		printf("%s key:<%s>\n",
-		       delaykey[i].retry ? "delay" : "stop",
-		       delaykey[i].str ? delaykey[i].str : "NULL");
-#  endif
+		debug_bootkeys("%s key:<%s>\n",
+			       delaykey[i].retry ? "delay" : "stop",
+			       delaykey[i].str ? delaykey[i].str : "NULL");
 	}
 
 	/* In order to keep up with incoming data, check timeout only
@@ -181,10 +170,9 @@
 			    memcmp (presskey + presskey_len - delaykey[i].len,
 				    delaykey[i].str,
 				    delaykey[i].len) == 0) {
-#  if DEBUG_BOOTKEYS
-				printf("got %skey\n",
-				       delaykey[i].retry ? "delay" : "stop");
-#  endif
+				debug_bootkeys("got %skey\n",
+					       delaykey[i].retry ? "delay" :
+					       "stop");
 
 #  ifdef CONFIG_BOOT_RETRY_TIME
 				/* don't retry auto boot */
@@ -196,10 +184,8 @@
 		}
 	} while (!abort && get_ticks() <= etime);
 
-#  if DEBUG_BOOTKEYS
 	if (!abort)
-		puts("key timeout\n");
-#  endif
+		debug_bootkeys("key timeout\n");
 
 #ifdef CONFIG_SILENT_CONSOLE
 	if (abort)
@@ -215,10 +201,7 @@
 static int menukey = 0;
 #endif
 
-#ifndef CONFIG_MENU
-static inline
-#endif
-int abortboot(int bootdelay)
+static int abortboot_normal(int bootdelay)
 {
 	int abort = 0;
 	unsigned long ts;
@@ -275,6 +258,15 @@
 	return abort;
 }
 # endif	/* CONFIG_AUTOBOOT_KEYED */
+
+static int abortboot(int bootdelay)
+{
+#ifdef CONFIG_AUTOBOOT_KEYED
+	return abortboot_keyed(bootdelay);
+#else
+	return abortboot_normal(bootdelay);
+#endif
+}
 #endif	/* CONFIG_BOOTDELAY */
 
 /*
@@ -342,93 +334,35 @@
 }
 #endif /* CONFIG_OF_CONTROL */
 
-
-/****************************************************************************/
-
-void main_loop (void)
+#ifdef CONFIG_BOOTDELAY
+static void process_boot_delay(void)
 {
-#ifndef CONFIG_SYS_HUSH_PARSER
-	static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
-	int len;
-	int rc = 1;
-	int flag;
-#endif
-#if defined(CONFIG_BOOTDELAY) && defined(CONFIG_OF_CONTROL)
+#ifdef CONFIG_OF_CONTROL
 	char *env;
 #endif
-#if defined(CONFIG_BOOTDELAY)
 	char *s;
 	int bootdelay;
-#endif
-#ifdef CONFIG_PREBOOT
-	char *p;
-#endif
 #ifdef CONFIG_BOOTCOUNT_LIMIT
 	unsigned long bootcount = 0;
 	unsigned long bootlimit = 0;
-	char *bcs;
-	char bcs_set[16];
 #endif /* CONFIG_BOOTCOUNT_LIMIT */
 
-	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
-
 #ifdef CONFIG_BOOTCOUNT_LIMIT
 	bootcount = bootcount_load();
 	bootcount++;
 	bootcount_store (bootcount);
-	sprintf (bcs_set, "%lu", bootcount);
-	setenv ("bootcount", bcs_set);
-	bcs = getenv ("bootlimit");
-	bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;
+	setenv_ulong("bootcount", bootcount);
+	bootlimit = getenv_ulong("bootlimit", 10, 0);
 #endif /* CONFIG_BOOTCOUNT_LIMIT */
 
-#ifdef CONFIG_MODEM_SUPPORT
-	debug ("DEBUG: main_loop:   do_mdm_init=%d\n", do_mdm_init);
-	if (do_mdm_init) {
-		char *str = strdup(getenv("mdm_cmd"));
-		setenv ("preboot", str);  /* set or delete definition */
-		if (str != NULL)
-			free (str);
-		mdm_init(); /* wait for modem connection */
-	}
-#endif  /* CONFIG_MODEM_SUPPORT */
-
-#ifdef CONFIG_VERSION_VARIABLE
-	{
-		setenv ("ver", version_string);  /* set version variable */
-	}
-#endif /* CONFIG_VERSION_VARIABLE */
-
-#ifdef CONFIG_SYS_HUSH_PARSER
-	u_boot_hush_start ();
-#endif
-
-#if defined(CONFIG_HUSH_INIT_VAR)
-	hush_init_var ();
-#endif
-
-#ifdef CONFIG_PREBOOT
-	if ((p = getenv ("preboot")) != NULL) {
-# ifdef CONFIG_AUTOBOOT_KEYED
-		int prev = disable_ctrlc(1);	/* disable Control C checking */
-# endif
-
-		run_command_list(p, -1, 0);
-
-# ifdef CONFIG_AUTOBOOT_KEYED
-		disable_ctrlc(prev);	/* restore Control C checking */
-# endif
-	}
-#endif /* CONFIG_PREBOOT */
-
-#if defined(CONFIG_UPDATE_TFTP)
-	update_tftp (0UL);
-#endif /* CONFIG_UPDATE_TFTP */
-
-#if defined(CONFIG_BOOTDELAY)
 	s = getenv ("bootdelay");
 	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
 
+#ifdef CONFIG_OF_CONTROL
+	bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
+			bootdelay);
+#endif
+
 	debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
 
 #if defined(CONFIG_MENU_SHOW)
@@ -474,26 +408,88 @@
 	debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
 
 	if (bootdelay != -1 && s && !abortboot(bootdelay)) {
-# ifdef CONFIG_AUTOBOOT_KEYED
+#ifdef CONFIG_AUTOBOOT_KEYED
 		int prev = disable_ctrlc(1);	/* disable Control C checking */
-# endif
+#endif
 
 		run_command_list(s, -1, 0);
 
-# ifdef CONFIG_AUTOBOOT_KEYED
+#ifdef CONFIG_AUTOBOOT_KEYED
 		disable_ctrlc(prev);	/* restore Control C checking */
-# endif
+#endif
 	}
 
-# ifdef CONFIG_MENUKEY
+#ifdef CONFIG_MENUKEY
 	if (menukey == CONFIG_MENUKEY) {
 		s = getenv("menucmd");
 		if (s)
 			run_command_list(s, -1, 0);
 	}
 #endif /* CONFIG_MENUKEY */
+}
 #endif /* CONFIG_BOOTDELAY */
 
+void main_loop(void)
+{
+#ifndef CONFIG_SYS_HUSH_PARSER
+	static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
+	int len;
+	int rc = 1;
+	int flag;
+#endif
+#ifdef CONFIG_PREBOOT
+	char *p;
+#endif
+
+	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
+
+#ifdef CONFIG_MODEM_SUPPORT
+	debug("DEBUG: main_loop:   do_mdm_init=%d\n", do_mdm_init);
+	if (do_mdm_init) {
+		char *str = strdup(getenv("mdm_cmd"));
+		setenv("preboot", str);  /* set or delete definition */
+		if (str != NULL)
+			free(str);
+		mdm_init(); /* wait for modem connection */
+	}
+#endif  /* CONFIG_MODEM_SUPPORT */
+
+#ifdef CONFIG_VERSION_VARIABLE
+	{
+		setenv("ver", version_string);  /* set version variable */
+	}
+#endif /* CONFIG_VERSION_VARIABLE */
+
+#ifdef CONFIG_SYS_HUSH_PARSER
+	u_boot_hush_start();
+#endif
+
+#if defined(CONFIG_HUSH_INIT_VAR)
+	hush_init_var();
+#endif
+
+#ifdef CONFIG_PREBOOT
+	p = getenv("preboot");
+	if (p != NULL) {
+# ifdef CONFIG_AUTOBOOT_KEYED
+		int prev = disable_ctrlc(1);	/* disable Control C checking */
+# endif
+
+		run_command_list(p, -1, 0);
+
+# ifdef CONFIG_AUTOBOOT_KEYED
+		disable_ctrlc(prev);	/* restore Control C checking */
+# endif
+	}
+#endif /* CONFIG_PREBOOT */
+
+#if defined(CONFIG_UPDATE_TFTP)
+	update_tftp(0UL);
+#endif /* CONFIG_UPDATE_TFTP */
+
+#ifdef CONFIG_BOOTDELAY
+	process_boot_delay();
+#endif
 	/*
 	 * Main Loop for Monitor Command Processing
 	 */
@@ -1080,20 +1076,20 @@
 		 * Special character handling
 		 */
 		switch (c) {
-		case '\r':				/* Enter		*/
+		case '\r':			/* Enter		*/
 		case '\n':
 			*p = '\0';
 			puts ("\r\n");
-			return (p - p_buf);
+			return p - p_buf;
 
-		case '\0':				/* nul			*/
+		case '\0':			/* nul			*/
 			continue;
 
-		case 0x03:				/* ^C - break		*/
+		case 0x03:			/* ^C - break		*/
 			p_buf[0] = '\0';	/* discard input */
-			return (-1);
+			return -1;
 
-		case 0x15:				/* ^U - erase line	*/
+		case 0x15:			/* ^U - erase line	*/
 			while (col > plen) {
 				puts (erase_seq);
 				--col;
@@ -1102,15 +1098,15 @@
 			n = 0;
 			continue;
 
-		case 0x17:				/* ^W - erase word	*/
+		case 0x17:			/* ^W - erase word	*/
 			p=delete_char(p_buf, p, &col, &n, plen);
 			while ((n > 0) && (*p != ' ')) {
 				p=delete_char(p_buf, p, &col, &n, plen);
 			}
 			continue;
 
-		case 0x08:				/* ^H  - backspace	*/
-		case 0x7F:				/* DEL - backspace	*/
+		case 0x08:			/* ^H  - backspace	*/
+		case 0x7F:			/* DEL - backspace	*/
 			p=delete_char(p_buf, p, &col, &n, plen);
 			continue;
 
@@ -1119,7 +1115,7 @@
 			 * Must be a normal character then
 			 */
 			if (n < CONFIG_SYS_CBSIZE-2) {
-				if (c == '\t') {	/* expand TABs		*/
+				if (c == '\t') {	/* expand TABs */
 #ifdef CONFIG_AUTO_COMPLETE
 					/* if auto completion triggered just continue */
 					*p = '\0';
@@ -1134,7 +1130,7 @@
 					char buf[2];
 
 					/*
-					 * Echo input using puts() to force am
+					 * Echo input using puts() to force an
 					 * LCD flush if we are using an LCD
 					 */
 					++col;
@@ -1192,9 +1188,7 @@
 {
 	int nargs = 0;
 
-#ifdef DEBUG_PARSER
-	printf ("parse_line: \"%s\"\n", line);
-#endif
+	debug_parser("parse_line: \"%s\"\n", line);
 	while (nargs < CONFIG_SYS_MAXARGS) {
 
 		/* skip any white space */
@@ -1203,10 +1197,8 @@
 
 		if (*line == '\0') {	/* end of line, no more args	*/
 			argv[nargs] = NULL;
-#ifdef DEBUG_PARSER
-		printf ("parse_line: nargs=%d\n", nargs);
-#endif
-			return (nargs);
+			debug_parser("parse_line: nargs=%d\n", nargs);
+			return nargs;
 		}
 
 		argv[nargs++] = line;	/* begin of argument string	*/
@@ -1217,10 +1209,8 @@
 
 		if (*line == '\0') {	/* end of line, no more args	*/
 			argv[nargs] = NULL;
-#ifdef DEBUG_PARSER
-		printf ("parse_line: nargs=%d\n", nargs);
-#endif
-			return (nargs);
+			debug_parser("parse_line: nargs=%d\n", nargs);
+			return nargs;
 		}
 
 		*line++ = '\0';		/* terminate current arg	 */
@@ -1228,9 +1218,7 @@
 
 	printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS);
 
-#ifdef DEBUG_PARSER
-	printf ("parse_line: nargs=%d\n", nargs);
-#endif
+	debug_parser("parse_line: nargs=%d\n", nargs);
 	return (nargs);
 }
 
@@ -1248,12 +1236,10 @@
 	/* 1 = waiting for '(' or '{' */
 	/* 2 = waiting for ')' or '}' */
 	/* 3 = waiting for '''  */
-#ifdef DEBUG_PARSER
 	char *output_start = output;
 
-	printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen (input),
-		input);
-#endif
+	debug_parser("[PROCESS_MACROS] INPUT len %zd: \"%s\"\n", strlen(input),
+		     input);
 
 	prev = '\0';		/* previous character   */
 
@@ -1341,10 +1327,8 @@
 	else
 		*(output - 1) = 0;
 
-#ifdef DEBUG_PARSER
-	printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
-		strlen (output_start), output_start);
-#endif
+	debug_parser("[PROCESS_MACROS] OUTPUT len %zd: \"%s\"\n",
+		     strlen(output_start), output_start);
 }
 
 /****************************************************************************
@@ -1375,12 +1359,12 @@
 	int repeatable = 1;
 	int rc = 0;
 
-#ifdef DEBUG_PARSER
-	printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
-	puts (cmd ? cmd : "NULL");	/* use puts - string may be loooong */
-	puts ("\"\n");
-#endif
-
+	debug_parser("[RUN_COMMAND] cmd[%p]=\"", cmd);
+	if (DEBUG_PARSER) {
+		/* use puts - string may be loooong */
+		puts(cmd ? cmd : "NULL");
+		puts("\"\n");
+	}
 	clear_ctrlc();		/* forget any previous Control C */
 
 	if (!cmd || !*cmd) {
@@ -1398,9 +1382,7 @@
 	 * repeatable commands
 	 */
 
-#ifdef DEBUG_PARSER
-	printf ("[PROCESS_SEPARATORS] %s\n", cmd);
-#endif
+	debug_parser("[PROCESS_SEPARATORS] %s\n", cmd);
 	while (*str) {
 
 		/*
@@ -1429,9 +1411,7 @@
 		}
 		else
 			str = sep;	/* no more commands for next pass */
-#ifdef DEBUG_PARSER
-		printf ("token: \"%s\"\n", token);
-#endif
+		debug_parser("token: \"%s\"\n", token);
 
 		/* find macros in this token and replace them */
 		process_macros (token, finaltoken);
diff --git a/disk/part_efi.c b/disk/part_efi.c
index 5986589..fb5e9f0 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -372,7 +372,7 @@
 	u32 offset = (u32)le32_to_cpu(gpt_h->first_usable_lba);
 	ulong start;
 	int i, k;
-	size_t name_len;
+	size_t efiname_len, dosname_len;
 #ifdef CONFIG_PARTITION_UUIDS
 	char *str_uuid;
 #endif
@@ -420,9 +420,14 @@
 		       sizeof(gpt_entry_attributes));
 
 		/* partition name */
-		name_len = sizeof(gpt_e[i].partition_name)
+		efiname_len = sizeof(gpt_e[i].partition_name)
 			/ sizeof(efi_char16_t);
-		for (k = 0; k < name_len; k++)
+		dosname_len = sizeof(partitions[i].name);
+
+		memset(gpt_e[i].partition_name, 0,
+		       sizeof(gpt_e[i].partition_name));
+
+		for (k = 0; k < min(dosname_len, efiname_len); k++)
 			gpt_e[i].partition_name[k] =
 				(efi_char16_t)(partitions[i].name[k]);
 
diff --git a/drivers/input/key_matrix.c b/drivers/input/key_matrix.c
index 946a186..c900e45 100644
--- a/drivers/input/key_matrix.c
+++ b/drivers/input/key_matrix.c
@@ -154,54 +154,42 @@
 	return map;
 }
 
-int key_matrix_decode_fdt(struct key_matrix *config, const void *blob,
-			  int node)
+int key_matrix_decode_fdt(struct key_matrix *config, const void *blob, int node)
 {
 	const struct fdt_property *prop;
-	const char prefix[] = "linux,";
-	int plen = sizeof(prefix) - 1;
-	int offset;
+	int proplen;
+	uchar *plain_keycode;
 
-	/* Check each property name for ones that we understand */
-	for (offset = fdt_first_property_offset(blob, node);
-		      offset > 0;
-		      offset = fdt_next_property_offset(blob, offset)) {
-		const char *name;
-		int len;
+	prop = fdt_get_property(blob, node, "linux,keymap", &proplen);
+	/* Basic keymap is required */
+	if (!prop) {
+		debug("%s: cannot find keycode-plain map\n", __func__);
+		return -1;
+	}
 
-		prop = fdt_get_property_by_offset(blob, offset, NULL);
-		name = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
-		len = strlen(name);
+	plain_keycode = create_keymap(config, (u32 *)prop->data,
+		proplen, KEY_FN, &config->fn_pos);
+	config->plain_keycode = plain_keycode;
+	/* Conversion error -> fail */
+	if (!config->plain_keycode)
+		return -1;
 
-		/* Name needs to match "1,<type>keymap" */
-		debug("%s: property '%s'\n", __func__, name);
-		if (strncmp(name, prefix, plen) ||
-				len < plen + 6 ||
-				strcmp(name + len - 6, "keymap"))
-			continue;
+	prop = fdt_get_property(blob, node, "linux,fn-keymap", &proplen);
+	/* fn keymap is optional */
+	if (!prop)
+		goto done;
 
-		len -= plen + 6;
-		if (len == 0) {
-			config->plain_keycode = create_keymap(config,
-				(u32 *)prop->data, fdt32_to_cpu(prop->len),
-				KEY_FN, &config->fn_pos);
-		} else if (0 == strncmp(name + plen, "fn-", len)) {
-			config->fn_keycode = create_keymap(config,
-				(u32 *)prop->data, fdt32_to_cpu(prop->len),
-				-1, NULL);
-		} else {
-			debug("%s: unrecognised property '%s'\n", __func__,
-			      name);
-		}
-	}
-	debug("%s: Decoded key maps %p, %p from fdt\n", __func__,
-	      config->plain_keycode, config->fn_keycode);
-
-	if (!config->plain_keycode) {
-		debug("%s: cannot find keycode-plain map\n", __func__);
+	config->fn_keycode = create_keymap(config, (u32 *)prop->data,
+		proplen, -1, NULL);
+	/* Conversion error -> fail */
+	if (!config->fn_keycode) {
+		free(plain_keycode);
 		return -1;
 	}
 
+done:
+	debug("%s: Decoded key maps %p, %p from fdt\n", __func__,
+	      config->plain_keycode, config->fn_keycode);
 	return 0;
 }
 
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile
index e8c159c..913dd9c 100644
--- a/drivers/tpm/Makefile
+++ b/drivers/tpm/Makefile
@@ -25,9 +25,10 @@
 
 $(shell mkdir -p $(obj)slb9635_i2c)
 
-COBJS-$(CONFIG_GENERIC_LPC_TPM) = generic_lpc_tpm.o
-COBJS-$(CONFIG_INFINEON_TPM_I2C) += tis_i2c.o slb9635_i2c/tpm.o
-COBJS-$(CONFIG_INFINEON_TPM_I2C) += slb9635_i2c/tpm_tis_i2c.o
+# TODO: Merge tpm_tis_lpc.c with tpm.c
+COBJS-$(CONFIG_TPM_TIS_I2C) += tpm.o
+COBJS-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o
+COBJS-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/tpm/slb9635_i2c/compatibility.h b/drivers/tpm/slb9635_i2c/compatibility.h
deleted file mode 100644
index 62dc9fa..0000000
--- a/drivers/tpm/slb9635_i2c/compatibility.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2011 Infineon Technologies
- *
- * Authors:
- * Peter Huewe <huewe.external@infineon.com>
- *
- * Version: 2.1.1
- *
- * 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 _COMPATIBILITY_H_
-#define _COMPATIBILITY_H_
-
-/* all includes from U-Boot */
-#include <linux/types.h>
-#include <linux/unaligned/be_byteshift.h>
-#include <asm-generic/errno.h>
-#include <compiler.h>
-#include <common.h>
-
-/* extended error numbers from linux (see errno.h) */
-#define	ECANCELED	125	/* Operation Canceled */
-
-#define msleep(t) udelay((t)*1000)
-
-/* Timer frequency. Corresponds to msec timer resolution*/
-#define HZ             1000
-
-#define dev_dbg(dev, format, arg...) debug(format, ##arg)
-#define dev_err(dev, format, arg...) printf(format, ##arg)
-#define dev_info(dev, format, arg...) debug(format, ##arg)
-#define dbg_printf debug
-
-#endif
diff --git a/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c b/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c
deleted file mode 100644
index 82a41bf..0000000
--- a/drivers/tpm/slb9635_i2c/tpm_tis_i2c.c
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * Copyright (C) 2011 Infineon Technologies
- *
- * Authors:
- * Peter Huewe <huewe.external@infineon.com>
- *
- * Description:
- * Device driver for TCG/TCPA TPM (trusted platform module).
- * Specifications at www.trustedcomputinggroup.org
- *
- * This device driver implements the TPM interface as defined in
- * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
- * Infineon I2C Protocol Stack Specification v0.20.
- *
- * It is based on the Linux kernel driver tpm.c from Leendert van
- * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
- *
- * Version: 2.1.1
- *
- * 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, version 2 of the
- * License.
- *
- * 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 <i2c.h>
-#include <linux/types.h>
-
-#include "compatibility.h"
-#include "tpm.h"
-
-/* max. buffer size supported by our tpm */
-#ifdef TPM_BUFSIZE
-#undef TPM_BUFSIZE
-#endif
-#define TPM_BUFSIZE 1260
-/* Address of the TPM on the I2C bus */
-#define TPM_I2C_ADDR 0x20
-/* max. number of iterations after i2c NAK */
-#define MAX_COUNT 3
-
-#define SLEEP_DURATION 60 /*in usec*/
-
-/* max. number of iterations after i2c NAK for 'long' commands
- * we need this especially for sending TPM_READY, since the cleanup after the
- * transtion to the ready state may take some time, but it is unpredictable
- * how long it will take.
- */
-#define MAX_COUNT_LONG 50
-
-#define SLEEP_DURATION_LONG 210 /* in usec */
-
-/* expected value for DIDVID register */
-#define TPM_TIS_I2C_DID_VID 0x000b15d1L
-
-/* Structure to store I2C TPM specific stuff */
-struct tpm_inf_dev {
-	uint addr;
-	u8 buf[TPM_BUFSIZE + sizeof(u8)];	/* max. buffer size + addr */
-};
-
-static struct tpm_inf_dev tpm_dev = {
-	.addr = TPM_I2C_ADDR
-};
-
-/*
- * iic_tpm_read() - read from TPM register
- * @addr: register address to read from
- * @buffer: provided by caller
- * @len: number of bytes to read
- *
- * Read len bytes from TPM register and put them into
- * buffer (little-endian format, i.e. first byte is put into buffer[0]).
- *
- * NOTE: TPM is big-endian for multi-byte values. Multi-byte
- * values have to be swapped.
- *
- * Return -EIO on error, 0 on success.
- */
-int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
-{
-	int rc;
-	int count;
-	uint myaddr = addr;
-	/* we have to use uint here, uchar hangs the board */
-
-	for (count = 0; count < MAX_COUNT; count++) {
-		rc = i2c_write(tpm_dev.addr, 0, 0, (uchar *)&myaddr, 1);
-		if (rc == 0)
-			break; /*success, break to skip sleep*/
-
-		udelay(SLEEP_DURATION);
-	}
-
-	if (rc)
-		return -rc;
-
-	/* After the TPM has successfully received the register address it needs
-	 * some time, thus we're sleeping here again, before retrieving the data
-	 */
-	for (count = 0; count < MAX_COUNT; count++) {
-		udelay(SLEEP_DURATION);
-		rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len);
-		if (rc == 0)
-			break; /*success, break to skip sleep*/
-	}
-
-	if (rc)
-		return -rc;
-
-	return 0;
-}
-
-static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len,
-				unsigned int sleep_time,
-				u8 max_count)
-{
-	int rc = 0;
-	int count;
-
-	/* prepare send buffer */
-	tpm_dev.buf[0] = addr;
-	memcpy(&(tpm_dev.buf[1]), buffer, len);
-
-	for (count = 0; count < max_count; count++) {
-		rc = i2c_write(tpm_dev.addr, 0, 0, tpm_dev.buf, len + 1);
-		if (rc == 0)
-			break; /*success, break to skip sleep*/
-
-		udelay(sleep_time);
-	}
-
-	if (rc)
-		return -rc;
-
-	return 0;
-}
-
-/*
- * iic_tpm_write() - write to TPM register
- * @addr: register address to write to
- * @buffer: containing data to be written
- * @len: number of bytes to write
- *
- * Write len bytes from provided buffer to TPM register (little
- * endian format, i.e. buffer[0] is written as first byte).
- *
- * NOTE: TPM is big-endian for multi-byte values. Multi-byte
- * values have to be swapped.
- *
- * NOTE: use this function instead of the iic_tpm_write_generic function.
- *
- * Return -EIO on error, 0 on success
- */
-static int iic_tpm_write(u8 addr, u8 *buffer, size_t len)
-{
-	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION,
-			MAX_COUNT);
-}
-
-/*
- * This function is needed especially for the cleanup situation after
- * sending TPM_READY
- * */
-static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len)
-{
-	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG,
-			MAX_COUNT_LONG);
-}
-
-#define TPM_HEADER_SIZE 10
-
-enum tis_access {
-	TPM_ACCESS_VALID = 0x80,
-	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
-	TPM_ACCESS_REQUEST_PENDING = 0x04,
-	TPM_ACCESS_REQUEST_USE = 0x02,
-};
-
-enum tis_status {
-	TPM_STS_VALID = 0x80,
-	TPM_STS_COMMAND_READY = 0x40,
-	TPM_STS_GO = 0x20,
-	TPM_STS_DATA_AVAIL = 0x10,
-	TPM_STS_DATA_EXPECT = 0x08,
-};
-
-enum tis_defaults {
-	TIS_SHORT_TIMEOUT = 750,	/* ms */
-	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
-};
-
-#define	TPM_ACCESS(l)			(0x0000 | ((l) << 4))
-#define	TPM_STS(l)			(0x0001 | ((l) << 4))
-#define	TPM_DATA_FIFO(l)		(0x0005 | ((l) << 4))
-#define	TPM_DID_VID(l)			(0x0006 | ((l) << 4))
-
-static int check_locality(struct tpm_chip *chip, int loc)
-{
-	u8 buf;
-	int rc;
-
-	rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1);
-	if (rc < 0)
-		return rc;
-
-	if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
-		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
-		chip->vendor.locality = loc;
-		return loc;
-	}
-
-	return -1;
-}
-
-static void release_locality(struct tpm_chip *chip, int loc, int force)
-{
-	u8 buf;
-	if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0)
-		return;
-
-	if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
-			(TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
-		buf = TPM_ACCESS_ACTIVE_LOCALITY;
-		iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
-	}
-}
-
-static int request_locality(struct tpm_chip *chip, int loc)
-{
-	unsigned long start, stop;
-	u8 buf = TPM_ACCESS_REQUEST_USE;
-
-	if (check_locality(chip, loc) >= 0)
-		return loc; /* we already have the locality */
-
-	iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
-
-	/* wait for burstcount */
-	start = get_timer(0);
-	stop = chip->vendor.timeout_a;
-	do {
-		if (check_locality(chip, loc) >= 0)
-			return loc;
-		msleep(TPM_TIMEOUT);
-	} while (get_timer(start) < stop);
-
-	return -1;
-}
-
-static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
-{
-	/* NOTE: since i2c read may fail, return 0 in this case --> time-out */
-	u8 buf;
-	if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
-		return 0;
-	else
-		return buf;
-}
-
-static void tpm_tis_i2c_ready(struct tpm_chip *chip)
-{
-	/* this causes the current command to be aborted */
-	u8 buf = TPM_STS_COMMAND_READY;
-	iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1);
-}
-
-static ssize_t get_burstcount(struct tpm_chip *chip)
-{
-	unsigned long start, stop;
-	ssize_t burstcnt;
-	u8 buf[3];
-
-	/* wait for burstcount */
-	/* which timeout value, spec has 2 answers (c & d) */
-	start = get_timer(0);
-	stop = chip->vendor.timeout_d;
-	do {
-		/* Note: STS is little endian */
-		if (iic_tpm_read(TPM_STS(chip->vendor.locality) + 1, buf, 3)
-				< 0)
-			burstcnt = 0;
-		else
-			burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
-
-		if (burstcnt)
-			return burstcnt;
-		msleep(TPM_TIMEOUT);
-	} while (get_timer(start) < stop);
-
-	return -EBUSY;
-}
-
-static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
-			int *status)
-{
-	unsigned long start, stop;
-
-	/* check current status */
-	*status = tpm_tis_i2c_status(chip);
-	if ((*status & mask) == mask)
-		return 0;
-
-	start = get_timer(0);
-	stop = timeout;
-	do {
-		msleep(TPM_TIMEOUT);
-		*status = tpm_tis_i2c_status(chip);
-		if ((*status & mask) == mask)
-			return 0;
-
-	} while (get_timer(start) < stop);
-
-	return -ETIME;
-}
-
-static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
-{
-	size_t size = 0;
-	ssize_t burstcnt;
-	int rc;
-
-	while (size < count) {
-		burstcnt = get_burstcount(chip);
-
-		/* burstcount < 0 = tpm is busy */
-		if (burstcnt < 0)
-			return burstcnt;
-
-		/* limit received data to max. left */
-		if (burstcnt > (count - size))
-			burstcnt = count - size;
-
-		rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality),
-				  &(buf[size]),
-				  burstcnt);
-		if (rc == 0)
-			size += burstcnt;
-	}
-
-	return size;
-}
-
-static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
-{
-	int size = 0;
-	int expected, status;
-
-	if (count < TPM_HEADER_SIZE) {
-		size = -EIO;
-		goto out;
-	}
-
-	/* read first 10 bytes, including tag, paramsize, and result */
-	size = recv_data(chip, buf, TPM_HEADER_SIZE);
-	if (size < TPM_HEADER_SIZE) {
-		dev_err(chip->dev, "Unable to read header\n");
-		goto out;
-	}
-
-	expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE);
-	if ((size_t)expected > count) {
-		size = -EIO;
-		goto out;
-	}
-
-	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
-				expected - TPM_HEADER_SIZE);
-	if (size < expected) {
-		dev_err(chip->dev, "Unable to read remainder of result\n");
-		size = -ETIME;
-		goto out;
-	}
-
-	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
-	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
-		dev_err(chip->dev, "Error left over data\n");
-		size = -EIO;
-		goto out;
-	}
-
-out:
-	tpm_tis_i2c_ready(chip);
-	/* The TPM needs some time to clean up here,
-	 * so we sleep rather than keeping the bus busy
-	 */
-	udelay(2000);
-	release_locality(chip, chip->vendor.locality, 0);
-
-	return size;
-}
-
-static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
-{
-	int rc, status;
-	ssize_t burstcnt;
-	size_t count = 0;
-	u8 sts = TPM_STS_GO;
-
-	if (len > TPM_BUFSIZE)
-		return -E2BIG; /* command is too long for our tpm, sorry */
-
-	if (request_locality(chip, 0) < 0)
-		return -EBUSY;
-
-	status = tpm_tis_i2c_status(chip);
-	if ((status & TPM_STS_COMMAND_READY) == 0) {
-		tpm_tis_i2c_ready(chip);
-		if (wait_for_stat
-		    (chip, TPM_STS_COMMAND_READY,
-		     chip->vendor.timeout_b, &status) < 0) {
-			rc = -ETIME;
-			goto out_err;
-		}
-	}
-
-	while (count < len - 1) {
-		burstcnt = get_burstcount(chip);
-
-		/* burstcount < 0 = tpm is busy */
-		if (burstcnt < 0)
-			return burstcnt;
-
-		if (burstcnt > (len-1-count))
-			burstcnt = len-1-count;
-
-#ifdef CONFIG_TPM_I2C_BURST_LIMITATION
-		if (burstcnt > CONFIG_TPM_I2C_BURST_LIMITATION)
-			burstcnt = CONFIG_TPM_I2C_BURST_LIMITATION;
-#endif /* CONFIG_TPM_I2C_BURST_LIMITATION */
-
-		rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
-				   &(buf[count]), burstcnt);
-		if (rc == 0)
-			count += burstcnt;
-
-		wait_for_stat(chip, TPM_STS_VALID,
-			      chip->vendor.timeout_c, &status);
-
-		if ((status & TPM_STS_DATA_EXPECT) == 0) {
-			rc = -EIO;
-			goto out_err;
-		}
-	}
-
-	/* write last byte */
-	iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
-	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
-	if ((status & TPM_STS_DATA_EXPECT) != 0) {
-		rc = -EIO;
-		goto out_err;
-	}
-
-	/* go and do it */
-	iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);
-
-	return len;
-out_err:
-	tpm_tis_i2c_ready(chip);
-	/* The TPM needs some time to clean up here,
-	 * so we sleep rather than keeping the bus busy
-	 */
-	udelay(2000);
-	release_locality(chip, chip->vendor.locality, 0);
-
-	return rc;
-}
-
-static struct tpm_vendor_specific tpm_tis_i2c = {
-	.status = tpm_tis_i2c_status,
-	.recv = tpm_tis_i2c_recv,
-	.send = tpm_tis_i2c_send,
-	.cancel = tpm_tis_i2c_ready,
-	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
-	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
-	.req_canceled = TPM_STS_COMMAND_READY,
-};
-
-/* initialisation of i2c tpm */
-
-
-int tpm_vendor_init(uint32_t dev_addr)
-{
-	u32 vendor;
-	uint old_addr;
-	int rc = 0;
-	struct tpm_chip *chip;
-
-	old_addr = tpm_dev.addr;
-	if (dev_addr != 0)
-		tpm_dev.addr = dev_addr;
-
-	chip = tpm_register_hardware(&tpm_tis_i2c);
-	if (chip < 0) {
-		rc = -ENODEV;
-		goto out_err;
-	}
-
-	/* Disable interrupts (not supported) */
-	chip->vendor.irq = 0;
-
-	/* Default timeouts */
-	chip->vendor.timeout_a = TIS_SHORT_TIMEOUT;
-	chip->vendor.timeout_b = TIS_LONG_TIMEOUT;
-	chip->vendor.timeout_c = TIS_SHORT_TIMEOUT;
-	chip->vendor.timeout_d = TIS_SHORT_TIMEOUT;
-
-	if (request_locality(chip, 0) != 0) {
-		rc = -ENODEV;
-		goto out_err;
-	}
-
-	/* read four bytes from DID_VID register */
-	if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) {
-		rc = -EIO;
-		goto out_release;
-	}
-
-	/* create DID_VID register value, after swapping to little-endian */
-	vendor = be32_to_cpu(vendor);
-
-	if (vendor != TPM_TIS_I2C_DID_VID) {
-		rc = -ENODEV;
-		goto out_release;
-	}
-
-	dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16);
-
-	/*
-	 * A timeout query to TPM can be placed here.
-	 * Standard timeout values are used so far
-	 */
-
-	return 0;
-
-out_release:
-	release_locality(chip, 0, 1);
-
-out_err:
-	tpm_dev.addr = old_addr;
-	return rc;
-}
-
-void tpm_vendor_cleanup(struct tpm_chip *chip)
-{
-	release_locality(chip, chip->vendor.locality, 1);
-}
diff --git a/drivers/tpm/tis_i2c.c b/drivers/tpm/tis_i2c.c
index e818fba..22554e1 100644
--- a/drivers/tpm/tis_i2c.c
+++ b/drivers/tpm/tis_i2c.c
@@ -68,6 +68,10 @@
 
 	node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
 	if (node < 0) {
+		node = fdtdec_next_compatible(blob, 0,
+					      COMPAT_INFINEON_SLB9645_TPM);
+	}
+	if (node < 0) {
 		debug("%s: Node not found\n", __func__);
 		return -1;
 	}
diff --git a/drivers/tpm/slb9635_i2c/tpm.c b/drivers/tpm/tpm.c
similarity index 63%
rename from drivers/tpm/slb9635_i2c/tpm.c
rename to drivers/tpm/tpm.c
index 496c48e..b657334 100644
--- a/drivers/tpm/slb9635_i2c/tpm.c
+++ b/drivers/tpm/tpm.c
@@ -32,11 +32,30 @@
  * MA 02111-1307 USA
  */
 
-#include <malloc.h>
-#include "tpm.h"
+#include <config.h>
+#include <common.h>
+#include <compiler.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <tpm.h>
+#include <asm-generic/errno.h>
+#include <linux/types.h>
+#include <linux/unaligned/be_byteshift.h>
 
-/* global structure for tpm chip data */
-struct tpm_chip g_chip;
+#include "tpm_private.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* TPM configuration */
+struct tpm {
+	int i2c_bus;
+	int slave_addr;
+	char inited;
+	int old_bus;
+} tpm;
+
+/* Global structure for tpm chip data */
+static struct tpm_chip g_chip;
 
 enum tpm_duration {
 	TPM_SHORT = 0,
@@ -45,9 +64,18 @@
 	TPM_UNDEFINED,
 };
 
-#define TPM_MAX_ORDINAL 243
-#define TPM_MAX_PROTECTED_ORDINAL 12
-#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+/* Extended error numbers from linux (see errno.h) */
+#define ECANCELED	125	/* Operation Canceled */
+
+/* Timer frequency. Corresponds to msec timer resolution*/
+#define HZ		1000
+
+#define TPM_MAX_ORDINAL			243
+#define TPM_MAX_PROTECTED_ORDINAL	12
+#define TPM_PROTECTED_ORDINAL_MASK	0xFF
+
+#define TPM_CMD_COUNT_BYTE	2
+#define TPM_CMD_ORDINAL_BYTE	6
 
 /*
  * Array with one entry per ordinal defining the maximum amount
@@ -318,34 +346,31 @@
 	TPM_MEDIUM,
 };
 
-/*
- * Returns max number of milliseconds to wait
- */
-unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
+/* Returns max number of milliseconds to wait */
+static unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
+		u32 ordinal)
 {
 	int duration_idx = TPM_UNDEFINED;
 	int duration = 0;
 
-	if (ordinal < TPM_MAX_ORDINAL)
+	if (ordinal < TPM_MAX_ORDINAL) {
 		duration_idx = tpm_ordinal_duration[ordinal];
-	else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
-		 TPM_MAX_PROTECTED_ORDINAL)
-		duration_idx =
-		    tpm_protected_ordinal_duration[ordinal &
-						   TPM_PROTECTED_ORDINAL_MASK];
+	} else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+			TPM_MAX_PROTECTED_ORDINAL) {
+		duration_idx = tpm_protected_ordinal_duration[
+				ordinal & TPM_PROTECTED_ORDINAL_MASK];
+	}
 
 	if (duration_idx != TPM_UNDEFINED)
 		duration = chip->vendor.duration[duration_idx];
+
 	if (duration <= 0)
-		return 2 * 60 * HZ; /*two minutes timeout*/
+		return 2 * 60 * HZ; /* Two minutes timeout */
 	else
 		return duration;
 }
 
-#define TPM_CMD_COUNT_BYTE 2
-#define TPM_CMD_ORDINAL_BYTE 6
-
-ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz)
+static ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz)
 {
 	ssize_t rc;
 	u32 count, ordinal;
@@ -358,18 +383,17 @@
 	ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
 
 	if (count == 0) {
-		dev_err(chip->dev, "no data\n");
+		error("no data\n");
 		return -ENODATA;
 	}
 	if (count > bufsiz) {
-		dev_err(chip->dev,
-			"invalid count value %x %zx\n", count, bufsiz);
+		error("invalid count value %x %zx\n", count, bufsiz);
 		return -E2BIG;
 	}
 
 	rc = chip->vendor.send(chip, (u8 *)buf, count);
 	if (rc < 0) {
-		dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc);
+		error("tpm_transmit: tpm_send: error %zd\n", rc);
 		goto out;
 	}
 
@@ -379,47 +403,126 @@
 	start = get_timer(0);
 	stop = tpm_calc_ordinal_duration(chip, ordinal);
 	do {
-		dbg_printf("waiting for status...\n");
+		debug("waiting for status...\n");
 		u8 status = chip->vendor.status(chip);
 		if ((status & chip->vendor.req_complete_mask) ==
 		    chip->vendor.req_complete_val) {
-			dbg_printf("...got it;\n");
+			debug("...got it;\n");
 			goto out_recv;
 		}
 
 		if ((status == chip->vendor.req_canceled)) {
-			dev_err(chip->dev, "Operation Canceled\n");
+			error("Operation Canceled\n");
 			rc = -ECANCELED;
 			goto out;
 		}
-		msleep(TPM_TIMEOUT);
+		udelay(TPM_TIMEOUT * 1000);
 	} while (get_timer(start) < stop);
 
 	chip->vendor.cancel(chip);
-	dev_err(chip->dev, "Operation Timed out\n");
+	error("Operation Timed out\n");
 	rc = -ETIME;
 	goto out;
 
 out_recv:
-
-	dbg_printf("out_recv: reading response...\n");
+	debug("out_recv: reading response...\n");
 	rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE);
 	if (rc < 0)
-		dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc);
+		error("tpm_transmit: tpm_recv: error %zd\n", rc);
+
 out:
 	return rc;
 }
 
+static int tpm_open(uint32_t dev_addr)
+{
+	int rc;
+	if (g_chip.is_open)
+		return -EBUSY;
+	rc = tpm_vendor_init(dev_addr);
+	if (rc < 0)
+		g_chip.is_open = 0;
+	return rc;
+}
+
-#define TPM_ERROR_SIZE 10
+static void tpm_close(void)
+{
+	if (g_chip.is_open) {
+		tpm_vendor_cleanup(&g_chip);
+		g_chip.is_open = 0;
+	}
+}
 
-enum tpm_capabilities {
-	TPM_CAP_PROP = cpu_to_be32(5),
-};
+static int tpm_select(void)
+{
+	int ret;
 
-enum tpm_sub_capabilities {
-	TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
-	TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
-};
+	tpm.old_bus = i2c_get_bus_num();
+	if (tpm.old_bus != tpm.i2c_bus) {
+		ret = i2c_set_bus_num(tpm.i2c_bus);
+		if (ret) {
+			debug("%s: Fail to set i2c bus %d\n", __func__,
+			      tpm.i2c_bus);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int tpm_deselect(void)
+{
+	int ret;
+
+	if (tpm.old_bus != i2c_get_bus_num()) {
+		ret = i2c_set_bus_num(tpm.old_bus);
+		if (ret) {
+			debug("%s: Fail to restore i2c bus %d\n",
+			      __func__, tpm.old_bus);
+			return -1;
+		}
+	}
+	tpm.old_bus = -1;
+	return 0;
+}
+
+/**
+ * Decode TPM configuration.
+ *
+ * @param dev	Returns a configuration of TPM device
+ * @return 0 if ok, -1 on error
+ */
+static int tpm_decode_config(struct tpm *dev)
+{
+#ifdef CONFIG_OF_CONTROL
+	const void *blob = gd->fdt_blob;
+	int node, parent;
+	int i2c_bus;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM);
+	if (node < 0) {
+		node = fdtdec_next_compatible(blob, 0,
+				COMPAT_INFINEON_SLB9645_TPM);
+	}
+	if (node < 0) {
+		debug("%s: Node not found\n", __func__);
+		return -1;
+	}
+	parent = fdt_parent_offset(blob, node);
+	if (parent < 0) {
+		debug("%s: Cannot find node parent\n", __func__);
+		return -1;
+	}
+	i2c_bus = i2c_get_bus_num_fdt(parent);
+	if (i2c_bus < 0)
+		return -1;
+	dev->i2c_bus = i2c_bus;
+	dev->slave_addr = fdtdec_get_addr(blob, node, "reg");
+#else
+	dev->i2c_bus = CONFIG_TPM_TIS_I2C_BUS_NUMBER;
+	dev->slave_addr = CONFIG_TPM_TIS_I2C_SLAVE_ADDRESS;
+#endif
+	return 0;
+}
 
 struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry)
 {
@@ -433,21 +536,94 @@
 	return chip;
 }
 
+int tis_init(void)
+{
+	if (tpm.inited)
+		return 0;
+
+	if (tpm_decode_config(&tpm))
+		return -1;
+
+	if (tpm_select())
+		return -1;
+
+	/*
+	 * Probe TPM twice; the first probing might fail because TPM is asleep,
+	 * and the probing can wake up TPM.
+	 */
+	if (i2c_probe(tpm.slave_addr) && i2c_probe(tpm.slave_addr)) {
+		debug("%s: fail to probe i2c addr 0x%x\n", __func__,
+		      tpm.slave_addr);
+		return -1;
+	}
+
+	tpm_deselect();
+
+	tpm.inited = 1;
+
+	return 0;
+}
+
-int tpm_open(uint32_t dev_addr)
+int tis_open(void)
 {
 	int rc;
-	if (g_chip.is_open)
-		return -EBUSY;
-	rc = tpm_vendor_init(dev_addr);
-	if (rc < 0)
-		g_chip.is_open = 0;
+
+	if (!tpm.inited)
+		return -1;
+
+	if (tpm_select())
+		return -1;
+
+	rc = tpm_open(tpm.slave_addr);
+
+	tpm_deselect();
+
 	return rc;
 }
 
-void tpm_close(void)
+int tis_close(void)
 {
-	if (g_chip.is_open) {
-		tpm_vendor_cleanup(&g_chip);
-		g_chip.is_open = 0;
+	if (!tpm.inited)
+		return -1;
+
+	if (tpm_select())
+		return -1;
+
+	tpm_close();
+
+	tpm_deselect();
+
+	return 0;
+}
+
+int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
+		uint8_t *recvbuf, size_t *rbuf_len)
+{
+	int len;
+	uint8_t buf[4096];
+
+	if (!tpm.inited)
+		return -1;
+
+	if (sizeof(buf) < sbuf_size)
+		return -1;
+
+	memcpy(buf, sendbuf, sbuf_size);
+
+	if (tpm_select())
+		return -1;
+
+	len = tpm_transmit(buf, sbuf_size);
+
+	tpm_deselect();
+
+	if (len < 10) {
+		*rbuf_len = 0;
+		return -1;
 	}
+
+	memcpy(recvbuf, buf, len);
+	*rbuf_len = len;
+
+	return 0;
 }
diff --git a/drivers/tpm/slb9635_i2c/tpm.h b/drivers/tpm/tpm_private.h
similarity index 71%
rename from drivers/tpm/slb9635_i2c/tpm.h
rename to drivers/tpm/tpm_private.h
index 9ddee86..888a074 100644
--- a/drivers/tpm/slb9635_i2c/tpm.h
+++ b/drivers/tpm/tpm_private.h
@@ -33,12 +33,11 @@
  * MA 02111-1307 USA
  */
 
-#ifndef _TPM_H_
-#define _TPM_H_
+#ifndef _TPM_PRIVATE_H_
+#define _TPM_PRIVATE_H_
 
 #include <linux/compiler.h>
-
-#include "compatibility.h"
+#include <linux/types.h>
 
 enum tpm_timeout {
 	TPM_TIMEOUT = 5,	/* msecs */
@@ -47,13 +46,9 @@
 /* Size of external transmit buffer (used in tpm_transmit)*/
 #define TPM_BUFSIZE 4096
 
-/* Index of fields in TPM command buffer */
-#define TPM_CMD_SIZE_BYTE 2
-#define TPM_CMD_ORDINAL_BYTE 6
-
 /* Index of Count field in TPM response buffer */
-#define TPM_RSP_SIZE_BYTE 2
-#define TPM_RSP_RC_BYTE 6
+#define TPM_RSP_SIZE_BYTE	2
+#define TPM_RSP_RC_BYTE		6
 
 struct tpm_chip;
 
@@ -65,10 +60,10 @@
 	int (*recv) (struct tpm_chip *, u8 *, size_t);
 	int (*send) (struct tpm_chip *, u8 *, size_t);
 	void (*cancel) (struct tpm_chip *);
-	 u8(*status) (struct tpm_chip *);
+	u8(*status) (struct tpm_chip *);
 	int locality;
-	unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* msec */
-	unsigned long duration[3];	/* msec */
+	unsigned long timeout_a, timeout_b, timeout_c, timeout_d;  /* msec */
+	unsigned long duration[3];  /* msec */
 };
 
 struct tpm_chip {
@@ -132,30 +127,11 @@
 	union tpm_cmd_params params;
 } __packed;
 
-
-/* ---------- Interface for TPM vendor ------------ */
-
-extern struct tpm_chip *tpm_register_hardware(
-	const struct tpm_vendor_specific *);
+struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *);
 
-extern int tpm_vendor_init(uint32_t dev_addr);
+int tpm_vendor_init(uint32_t dev_addr);
 
-extern void tpm_vendor_cleanup(struct tpm_chip *chip);
-
-/* ---------- Interface for TDDL ------------------- */
-
-/*
- * if dev_addr != 0 - redefines TPM device address
- * Returns < 0 on error, 0 on success.
- */
-extern int tpm_open(uint32_t dev_addr);
-
-extern void tpm_close(void);
+void tpm_vendor_cleanup(struct tpm_chip *chip);
 
-/*
- * Transmit bufsiz bytes out of buf to TPM and get results back in buf, too.
- * Returns < 0 on error, 0 on success.
- */
-extern ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz);
 
 #endif
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c
new file mode 100644
index 0000000..2dd8501
--- /dev/null
+++ b/drivers/tpm/tpm_tis_i2c.c
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2011 Infineon Technologies
+ *
+ * Authors:
+ * Peter Huewe <huewe.external@infineon.com>
+ *
+ * Description:
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
+ * Infineon I2C Protocol Stack Specification v0.20.
+ *
+ * It is based on the Linux kernel driver tpm.c from Leendert van
+ * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
+ *
+ * Version: 2.1.1
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * 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 <fdtdec.h>
+#include <compiler.h>
+#include <i2c.h>
+#include <tpm.h>
+#include <asm-generic/errno.h>
+#include <linux/types.h>
+#include <linux/unaligned/be_byteshift.h>
+
+#include "tpm_private.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Address of the TPM on the I2C bus */
+#define TPM_I2C_ADDR		0x20
+
+/* Max buffer size supported by our tpm */
+#define TPM_DEV_BUFSIZE		1260
+
+/* Max number of iterations after i2c NAK */
+#define MAX_COUNT		3
+
+/*
+ * Max number of iterations after i2c NAK for 'long' commands
+ *
+ * We need this especially for sending TPM_READY, since the cleanup after the
+ * transtion to the ready state may take some time, but it is unpredictable
+ * how long it will take.
+ */
+#define MAX_COUNT_LONG		50
+
+#define SLEEP_DURATION		60	/* in usec */
+#define SLEEP_DURATION_LONG	210	/* in usec */
+
+#define TPM_HEADER_SIZE		10
+
+/*
+ * Expected value for DIDVID register
+ *
+ * The only device the system knows about at this moment is Infineon slb9635.
+ */
+#define TPM_TIS_I2C_DID_VID	0x000b15d1L
+
+enum tis_access {
+	TPM_ACCESS_VALID		= 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY	= 0x20,
+	TPM_ACCESS_REQUEST_PENDING	= 0x04,
+	TPM_ACCESS_REQUEST_USE		= 0x02,
+};
+
+enum tis_status {
+	TPM_STS_VALID			= 0x80,
+	TPM_STS_COMMAND_READY		= 0x40,
+	TPM_STS_GO			= 0x20,
+	TPM_STS_DATA_AVAIL		= 0x10,
+	TPM_STS_DATA_EXPECT		= 0x08,
+};
+
+enum tis_defaults {
+	TIS_SHORT_TIMEOUT		= 750,	/* ms */
+	TIS_LONG_TIMEOUT		= 2000,	/* ms */
+};
+
+/* expected value for DIDVID register */
+#define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L
+#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L
+
+enum i2c_chip_type {
+	SLB9635,
+	SLB9645,
+	UNKNOWN,
+};
+
+static const char * const chip_name[] = {
+	[SLB9635] = "slb9635tt",
+	[SLB9645] = "slb9645tt",
+	[UNKNOWN] = "unknown/fallback to slb9635",
+};
+
+#define	TPM_ACCESS(l)			(0x0000 | ((l) << 4))
+#define	TPM_STS(l)			(0x0001 | ((l) << 4))
+#define	TPM_DATA_FIFO(l)		(0x0005 | ((l) << 4))
+#define	TPM_DID_VID(l)			(0x0006 | ((l) << 4))
+
+/* Structure to store I2C TPM specific stuff */
+struct tpm_dev {
+	uint addr;
+	u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)];  /* Max buffer size + addr */
+	enum i2c_chip_type chip_type;
+};
+
+static struct tpm_dev tpm_dev = {
+	.addr = TPM_I2C_ADDR
+};
+
+static struct tpm_dev tpm_dev;
+
+/*
+ * iic_tpm_read() - read from TPM register
+ * @addr: register address to read from
+ * @buffer: provided by caller
+ * @len: number of bytes to read
+ *
+ * Read len bytes from TPM register and put them into
+ * buffer (little-endian format, i.e. first byte is put into buffer[0]).
+ *
+ * NOTE: TPM is big-endian for multi-byte values. Multi-byte
+ * values have to be swapped.
+ *
+ * Return -EIO on error, 0 on success.
+ */
+static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
+{
+	int rc;
+	int count;
+	uint32_t addrbuf = addr;
+
+	if ((tpm_dev.chip_type == SLB9635) || (tpm_dev.chip_type == UNKNOWN)) {
+		/* slb9635 protocol should work in both cases */
+		for (count = 0; count < MAX_COUNT; count++) {
+			rc = i2c_write(tpm_dev.addr, 0, 0,
+				       (uchar *)&addrbuf, 1);
+			if (rc == 0)
+				break;  /* Success, break to skip sleep */
+			udelay(SLEEP_DURATION);
+		}
+		if (rc)
+			return -rc;
+
+		/* After the TPM has successfully received the register address
+		 * it needs some time, thus we're sleeping here again, before
+		 * retrieving the data
+		 */
+		for (count = 0; count < MAX_COUNT; count++) {
+			udelay(SLEEP_DURATION);
+			rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len);
+			if (rc == 0)
+				break;  /* success, break to skip sleep */
+		}
+	} else {
+		/*
+		 * Use a combined read for newer chips.
+		 * Unfortunately the smbus functions are not suitable due to
+		 * the 32 byte limit of the smbus.
+		 * Retries should usually not be needed, but are kept just to
+		 * be safe on the safe side.
+		 */
+		for (count = 0; count < MAX_COUNT; count++) {
+			rc = i2c_read(tpm_dev.addr, addr, 1, buffer, len);
+			if (rc == 0)
+				break;  /* break here to skip sleep */
+			udelay(SLEEP_DURATION);
+		}
+	}
+
+	/* Take care of 'guard time' */
+	udelay(SLEEP_DURATION);
+	if (rc)
+		return -rc;
+
+	return 0;
+}
+
+static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len,
+		unsigned int sleep_time, u8 max_count)
+{
+	int rc = 0;
+	int count;
+
+	/* Prepare send buffer */
+	tpm_dev.buf[0] = addr;
+	memcpy(&(tpm_dev.buf[1]), buffer, len);
+
+	for (count = 0; count < max_count; count++) {
+		rc = i2c_write(tpm_dev.addr, 0, 0, tpm_dev.buf, len + 1);
+		if (rc == 0)
+			break;  /* Success, break to skip sleep */
+		udelay(sleep_time);
+	}
+
+	/* take care of 'guard time' */
+	udelay(SLEEP_DURATION);
+	if (rc)
+		return -rc;
+
+	return 0;
+}
+
+/*
+ * iic_tpm_write() - write to TPM register
+ * @addr: register address to write to
+ * @buffer: containing data to be written
+ * @len: number of bytes to write
+ *
+ * Write len bytes from provided buffer to TPM register (little
+ * endian format, i.e. buffer[0] is written as first byte).
+ *
+ * NOTE: TPM is big-endian for multi-byte values. Multi-byte
+ * values have to be swapped.
+ *
+ * NOTE: use this function instead of the iic_tpm_write_generic function.
+ *
+ * Return -EIO on error, 0 on success
+ */
+static int iic_tpm_write(u8 addr, u8 *buffer, size_t len)
+{
+	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION,
+			MAX_COUNT);
+}
+
+/*
+ * This function is needed especially for the cleanup situation after
+ * sending TPM_READY
+ */
+static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len)
+{
+	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG,
+			MAX_COUNT_LONG);
+}
+
+static int check_locality(struct tpm_chip *chip, int loc)
+{
+	const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID;
+	u8 buf;
+	int rc;
+
+	rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	if ((buf & mask) == mask) {
+		chip->vendor.locality = loc;
+		return loc;
+	}
+
+	return -1;
+}
+
+static void release_locality(struct tpm_chip *chip, int loc, int force)
+{
+	const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID;
+	u8 buf;
+
+	if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0)
+		return;
+
+	if (force || (buf & mask) == mask) {
+		buf = TPM_ACCESS_ACTIVE_LOCALITY;
+		iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
+	}
+}
+
+static int request_locality(struct tpm_chip *chip, int loc)
+{
+	unsigned long start, stop;
+	u8 buf = TPM_ACCESS_REQUEST_USE;
+
+	if (check_locality(chip, loc) >= 0)
+		return loc;  /* We already have the locality */
+
+	iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
+
+	/* Wait for burstcount */
+	start = get_timer(0);
+	stop = chip->vendor.timeout_a;
+	do {
+		if (check_locality(chip, loc) >= 0)
+			return loc;
+		udelay(TPM_TIMEOUT * 1000);
+	} while (get_timer(start) < stop);
+
+	return -1;
+}
+
+static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
+{
+	/* NOTE: Since i2c read may fail, return 0 in this case --> time-out */
+	u8 buf;
+
+	if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
+		return 0;
+	else
+		return buf;
+}
+
+static void tpm_tis_i2c_ready(struct tpm_chip *chip)
+{
+	/* This causes the current command to be aborted */
+	u8 buf = TPM_STS_COMMAND_READY;
+
+	iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1);
+}
+
+static ssize_t get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long start, stop;
+	ssize_t burstcnt;
+	u8 addr, buf[3];
+
+	/* Wait for burstcount */
+	/* XXX: Which timeout value? Spec has 2 answers (c & d) */
+	start = get_timer(0);
+	stop = chip->vendor.timeout_d;
+	do {
+		/* Note: STS is little endian */
+		addr = TPM_STS(chip->vendor.locality) + 1;
+		if (iic_tpm_read(addr, buf, 3) < 0)
+			burstcnt = 0;
+		else
+			burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
+
+		if (burstcnt)
+			return burstcnt;
+		udelay(TPM_TIMEOUT * 1000);
+	} while (get_timer(start) < stop);
+
+	return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+		int *status)
+{
+	unsigned long start, stop;
+
+	/* Check current status */
+	*status = tpm_tis_i2c_status(chip);
+	if ((*status & mask) == mask)
+		return 0;
+
+	start = get_timer(0);
+	stop = timeout;
+	do {
+		udelay(TPM_TIMEOUT * 1000);
+		*status = tpm_tis_i2c_status(chip);
+		if ((*status & mask) == mask)
+			return 0;
+	} while (get_timer(start) < stop);
+
+	return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	size_t size = 0;
+	ssize_t burstcnt;
+	int rc;
+
+	while (size < count) {
+		burstcnt = get_burstcount(chip);
+
+		/* burstcount < 0 -> tpm is busy */
+		if (burstcnt < 0)
+			return burstcnt;
+
+		/* Limit received data to max left */
+		if (burstcnt > (count - size))
+			burstcnt = count - size;
+
+		rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality),
+				&(buf[size]), burstcnt);
+		if (rc == 0)
+			size += burstcnt;
+	}
+
+	return size;
+}
+
+static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0;
+	int expected, status;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	/* Read first 10 bytes, including tag, paramsize, and result */
+	size = recv_data(chip, buf, TPM_HEADER_SIZE);
+	if (size < TPM_HEADER_SIZE) {
+		error("Unable to read header\n");
+		goto out;
+	}
+
+	expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE);
+	if ((size_t)expected > count) {
+		size = -EIO;
+		goto out;
+	}
+
+	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
+			expected - TPM_HEADER_SIZE);
+	if (size < expected) {
+		error("Unable to read remainder of result\n");
+		size = -ETIME;
+		goto out;
+	}
+
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
+	if (status & TPM_STS_DATA_AVAIL) {  /* Retry? */
+		error("Error left over data\n");
+		size = -EIO;
+		goto out;
+	}
+
+out:
+	tpm_tis_i2c_ready(chip);
+	/*
+	 * The TPM needs some time to clean up here,
+	 * so we sleep rather than keeping the bus busy
+	 */
+	udelay(2000);
+	release_locality(chip, chip->vendor.locality, 0);
+
+	return size;
+}
+
+static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc, status;
+	ssize_t burstcnt;
+	size_t count = 0;
+	int retry = 0;
+	u8 sts = TPM_STS_GO;
+
+	if (len > TPM_DEV_BUFSIZE)
+		return -E2BIG;  /* Command is too long for our tpm, sorry */
+
+	if (request_locality(chip, 0) < 0)
+		return -EBUSY;
+
+	status = tpm_tis_i2c_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_tis_i2c_ready(chip);
+		if (wait_for_stat(chip, TPM_STS_COMMAND_READY,
+				  chip->vendor.timeout_b, &status) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+
+	burstcnt = get_burstcount(chip);
+
+	/* burstcount < 0 -> tpm is busy */
+	if (burstcnt < 0)
+		return burstcnt;
+
+	while (count < len - 1) {
+		if (burstcnt > len - 1 - count)
+			burstcnt = len - 1 - count;
+
+#ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION
+		if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION)
+			burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION;
+#endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */
+
+		rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
+				&(buf[count]), burstcnt);
+		if (rc == 0)
+			count += burstcnt;
+		else {
+			retry++;
+			wait_for_stat(chip, TPM_STS_VALID,
+				      chip->vendor.timeout_c, &status);
+
+			if ((status & TPM_STS_DATA_EXPECT) == 0) {
+				rc = -EIO;
+				goto out_err;
+			}
+		}
+	}
+
+	/* Write last byte */
+	iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		rc = -EIO;
+		goto out_err;
+	}
+
+	/* Go and do it */
+	iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);
+
+	return len;
+
+out_err:
+	tpm_tis_i2c_ready(chip);
+	/*
+	 * The TPM needs some time to clean up here,
+	 * so we sleep rather than keeping the bus busy
+	 */
+	udelay(2000);
+	release_locality(chip, chip->vendor.locality, 0);
+
+	return rc;
+}
+
+static struct tpm_vendor_specific tpm_tis_i2c = {
+	.status = tpm_tis_i2c_status,
+	.recv = tpm_tis_i2c_recv,
+	.send = tpm_tis_i2c_send,
+	.cancel = tpm_tis_i2c_ready,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+};
+
+
+static enum i2c_chip_type tpm_vendor_chip_type(void)
+{
+#ifdef CONFIG_OF_CONTROL
+	const void *blob = gd->fdt_blob;
+
+	if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9645_TPM) >= 0)
+		return SLB9645;
+
+	if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9635_TPM) >= 0)
+		return SLB9635;
+#endif
+	return UNKNOWN;
+}
+
+/* Initialisation of i2c tpm */
+int tpm_vendor_init(uint32_t dev_addr)
+{
+	u32 vendor;
+	u32 expected_did_vid;
+	uint old_addr;
+	int rc = 0;
+	struct tpm_chip *chip;
+
+	old_addr = tpm_dev.addr;
+	if (dev_addr != 0)
+		tpm_dev.addr = dev_addr;
+
+	tpm_dev.chip_type = tpm_vendor_chip_type();
+
+	chip = tpm_register_hardware(&tpm_tis_i2c);
+	if (chip < 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* Disable interrupts (not supported) */
+	chip->vendor.irq = 0;
+
+	/* Default timeouts */
+	chip->vendor.timeout_a = TIS_SHORT_TIMEOUT;
+	chip->vendor.timeout_b = TIS_LONG_TIMEOUT;
+	chip->vendor.timeout_c = TIS_SHORT_TIMEOUT;
+	chip->vendor.timeout_d = TIS_SHORT_TIMEOUT;
+
+	if (request_locality(chip, 0) < 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* Read four bytes from DID_VID register */
+	if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) {
+		rc = -EIO;
+		goto out_release;
+	}
+
+	if (tpm_dev.chip_type == SLB9635) {
+		vendor = be32_to_cpu(vendor);
+		expected_did_vid = TPM_TIS_I2C_DID_VID_9635;
+	} else {
+		/* device id and byte order has changed for newer i2c tpms */
+		expected_did_vid = TPM_TIS_I2C_DID_VID_9645;
+	}
+
+	if (tpm_dev.chip_type != UNKNOWN && vendor != expected_did_vid) {
+		error("Vendor id did not match! ID was %08x\n", vendor);
+		rc = -ENODEV;
+		goto out_release;
+	}
+
+	debug("1.2 TPM (chip type %s device-id 0x%X)\n",
+	      chip_name[tpm_dev.chip_type], vendor >> 16);
+
+	/*
+	 * A timeout query to TPM can be placed here.
+	 * Standard timeout values are used so far
+	 */
+
+	return 0;
+
+out_release:
+	release_locality(chip, 0, 1);
+
+out_err:
+	tpm_dev.addr = old_addr;
+	return rc;
+}
+
+void tpm_vendor_cleanup(struct tpm_chip *chip)
+{
+	release_locality(chip, chip->vendor.locality, 1);
+}
diff --git a/drivers/tpm/generic_lpc_tpm.c b/drivers/tpm/tpm_tis_lpc.c
similarity index 100%
rename from drivers/tpm/generic_lpc_tpm.c
rename to drivers/tpm/tpm_tis_lpc.c
diff --git a/include/bootstage.h b/include/bootstage.h
index 6dc0422..ef07a87 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -37,6 +37,24 @@
 	BOOTSTAGEF_ALLOC	= 1 << 1,	/* Allocate an id */
 };
 
+/* bootstate sub-IDs used for kernel and ramdisk ranges */
+enum {
+	BOOTSTAGE_SUB_FORMAT,
+	BOOTSTAGE_SUB_FORMAT_OK,
+	BOOTSTAGE_SUB_NO_UNIT_NAME,
+	BOOTSTAGE_SUB_UNIT_NAME,
+	BOOTSTAGE_SUB_SUBNODE,
+
+	BOOTSTAGE_SUB_CHECK,
+	BOOTSTAGE_SUB_HASH = 5,
+	BOOTSTAGE_SUB_CHECK_ARCH = 5,
+	BOOTSTAGE_SUB_CHECK_ALL,
+	BOOTSTAGE_SUB_GET_DATA,
+	BOOTSTAGE_SUB_CHECK_ALL_OK = 7,
+	BOOTSTAGE_SUB_GET_DATA_OK,
+	BOOTSTAGE_SUB_LOAD,
+};
+
 /*
  * A list of boot stages that we know about. Each of these indicates the
  * state that we are at, and the action that we are about to perform. For
@@ -137,43 +155,24 @@
 	BOOTSTAGE_ID_NET_DONE_ERR,
 	BOOTSTAGE_ID_NET_DONE,
 
+	BOOTSTAGE_ID_FIT_FDT_START = 90,
 	/*
 	 * Boot stages related to loading a FIT image. Some of these are a
 	 * bit wonky.
 	 */
-	BOOTSTAGE_ID_FIT_FORMAT = 100,
-	BOOTSTAGE_ID_FIT_NO_UNIT_NAME,
-	BOOTSTAGE_ID_FIT_UNIT_NAME,
-	BOOTSTAGE_ID_FIT_CONFIG,
-	BOOTSTAGE_ID_FIT_CHECK_SUBIMAGE,
-	BOOTSTAGE_ID_FIT_CHECK_HASH = 104,
-
-	BOOTSTAGE_ID_FIT_CHECK_ARCH,
-	BOOTSTAGE_ID_FIT_CHECK_KERNEL,
-	BOOTSTAGE_ID_FIT_CHECKED,
+	BOOTSTAGE_ID_FIT_KERNEL_START = 100,
 
-	BOOTSTAGE_ID_FIT_KERNEL_INFO_ERR = 107,
-	BOOTSTAGE_ID_FIT_KERNEL_INFO,
+	BOOTSTAGE_ID_FIT_CONFIG = 110,
 	BOOTSTAGE_ID_FIT_TYPE,
+	BOOTSTAGE_ID_FIT_KERNEL_INFO,
 
 	BOOTSTAGE_ID_FIT_COMPRESSION,
 	BOOTSTAGE_ID_FIT_OS,
 	BOOTSTAGE_ID_FIT_LOADADDR,
 	BOOTSTAGE_ID_OVERWRITTEN,
 
-	BOOTSTAGE_ID_FIT_RD_FORMAT = 120,
-	BOOTSTAGE_ID_FIT_RD_FORMAT_OK,
-	BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME,
-	BOOTSTAGE_ID_FIT_RD_UNIT_NAME,
-	BOOTSTAGE_ID_FIT_RD_SUBNODE,
-
-	BOOTSTAGE_ID_FIT_RD_CHECK,
-	BOOTSTAGE_ID_FIT_RD_HASH = 125,
-	BOOTSTAGE_ID_FIT_RD_CHECK_ALL,
-	BOOTSTAGE_ID_FIT_RD_GET_DATA,
-	BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK = 127,
-	BOOTSTAGE_ID_FIT_RD_GET_DATA_OK,
-	BOOTSTAGE_ID_FIT_RD_LOAD,
+	/* Next 10 IDs used by BOOTSTAGE_SUB_... */
+	BOOTSTAGE_ID_FIT_RD_START = 120,	/* Ramdisk stages */
 
 	BOOTSTAGE_ID_IDE_FIT_READ = 140,
 	BOOTSTAGE_ID_IDE_FIT_READ_OK,
diff --git a/include/common.h b/include/common.h
index e682bd8..126891d 100644
--- a/include/common.h
+++ b/include/common.h
@@ -310,9 +310,6 @@
 int	parse_line (char *, char *[]);
 void	init_cmd_timeout(void);
 void	reset_cmd_timeout(void);
-#ifdef CONFIG_MENU
-int	abortboot(int bootdelay);
-#endif
 extern char console_buffer[];
 
 /* arch/$(ARCH)/lib/board.c */
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index f019134..cd2c078 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -305,8 +305,13 @@
 /* Defines for SPL */
 #define CONFIG_SPL
 #define CONFIG_SPL_FRAMEWORK
+/*
+ * Place the image at the start of the ROM defined image space.
+ * We limit our size to the ROM-defined downloaded image area, and use the
+ * rest of the space for stack.
+ */
 #define CONFIG_SPL_TEXT_BASE		0x402F0400
-#define CONFIG_SPL_MAX_SIZE		(101 * 1024)
+#define CONFIG_SPL_MAX_SIZE		(0x4030C000 - CONFIG_SPL_TEXT_BASE)
 #define CONFIG_SPL_STACK		CONFIG_SYS_INIT_SP_ADDR
 
 #define CONFIG_SPL_BSS_START_ADDR	0x80000000
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h
index be04a75..2fefdc8 100644
--- a/include/configs/coreboot.h
+++ b/include/configs/coreboot.h
@@ -90,7 +90,8 @@
 #endif
 
 /* Generic TPM interfaced through LPC bus */
-#define CONFIG_GENERIC_LPC_TPM
+#define CONFIG_TPM
+#define CONFIG_TPM_TIS_LPC
 #define CONFIG_TPM_TIS_BASE_ADDRESS        0xfed40000
 
 /*-----------------------------------------------------------------------
diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h
index 8a82892..41d6cf9 100644
--- a/include/configs/exynos5250-dt.h
+++ b/include/configs/exynos5250-dt.h
@@ -142,9 +142,9 @@
 /* TPM */
 #define CONFIG_TPM
 #define CONFIG_CMD_TPM
-#define CONFIG_INFINEON_TPM_I2C
-#define CONFIG_INFINEON_TPM_I2C_BUS 3
-#define CONFIG_INFINEON_TPM_I2C_ADDR 0x20
+#define CONFIG_TPM_TIS_I2C
+#define CONFIG_TPM_TIS_I2C_BUS_NUMBER	3
+#define CONFIG_TPM_TIS_I2C_SLAVE_ADDR	0x20
 
 /* MMC SPL */
 #define CONFIG_SPL
diff --git a/include/configs/igep0033.h b/include/configs/igep0033.h
index 1912d7d..12f28f8 100644
--- a/include/configs/igep0033.h
+++ b/include/configs/igep0033.h
@@ -214,8 +214,13 @@
 /* Defines for SPL */
 #define CONFIG_SPL
 #define CONFIG_SPL_FRAMEWORK
+/*
+ * Place the image at the start of the ROM defined image space.
+ * We limit our size to the ROM-defined downloaded image area, and use the
+ * rest of the space for stack.
+ */
 #define CONFIG_SPL_TEXT_BASE		0x402F0400
-#define CONFIG_SPL_MAX_SIZE		(101 * 1024)
+#define CONFIG_SPL_MAX_SIZE		(0x4030C000 - CONFIG_SPL_TEXT_BASE)
 #define CONFIG_SPL_STACK		CONFIG_SYS_INIT_SP_ADDR
 
 #define CONFIG_SPL_BSS_START_ADDR	0x80000000
diff --git a/include/configs/pcm051.h b/include/configs/pcm051.h
index 478f805..2ecd105 100644
--- a/include/configs/pcm051.h
+++ b/include/configs/pcm051.h
@@ -204,8 +204,13 @@
 /* Defines for SPL */
 #define CONFIG_SPL
 #define CONFIG_SPL_FRAMEWORK
+/*
+ * Place the image at the start of the ROM defined image space.
+ * We limit our size to the ROM-defined downloaded image area, and use the
+ * rest of the space for stack.
+ */
 #define CONFIG_SPL_TEXT_BASE		0x402F0400
-#define CONFIG_SPL_MAX_SIZE		(101 * 1024)
+#define CONFIG_SPL_MAX_SIZE		(0x4030C000 - CONFIG_SPL_TEXT_BASE)
 #define CONFIG_SPL_STACK		CONFIG_SYS_INIT_SP_ADDR
 
 #define CONFIG_SPL_BSS_START_ADDR	0x80000000
diff --git a/include/configs/pm9263.h b/include/configs/pm9263.h
index b60a9ad..6f6ddfa 100644
--- a/include/configs/pm9263.h
+++ b/include/configs/pm9263.h
@@ -355,7 +355,7 @@
 
 #define CONFIG_BOOTCOMMAND		"run flashboot"
 #define CONFIG_ROOTPATH			"/ronetix/rootfs"
-#define CONFIG_AUTOBOOT_PROMPT		"autoboot in %d seconds\n"
+#define CONFIG_AUTOBOOT_PROMPT		"autoboot in %d seconds\n", bootdelay
 
 #define CONFIG_CON_ROT			"fbcon=rotate:3 "
 #define CONFIG_BOOTARGS			"root=/dev/mtdblock4 rootfstype=jffs2 "\
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 4e8032b..1ece612 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -93,6 +93,7 @@
 	COMPAT_GENERIC_SPI_FLASH,	/* Generic SPI Flash chip */
 	COMPAT_MAXIM_98095_CODEC,	/* MAX98095 Codec */
 	COMPAT_INFINEON_SLB9635_TPM,	/* Infineon SLB9635 TPM */
+	COMPAT_INFINEON_SLB9645_TPM,	/* Infineon SLB9645 TPM */
 
 	COMPAT_COUNT,
 };
diff --git a/include/image.h b/include/image.h
index b8cc523..8ccc00b 100644
--- a/include/image.h
+++ b/include/image.h
@@ -402,6 +402,13 @@
 #endif
 void genimg_print_time(time_t timestamp);
 
+/* What to do with a image load address ('load = <> 'in the FIT) */
+enum fit_load_op {
+	FIT_LOAD_IGNORED,	/* Ignore load address */
+	FIT_LOAD_OPTIONAL,	/* Can be provided, but optional */
+	FIT_LOAD_REQUIRED,	/* Must be provided */
+};
+
 #ifndef USE_HOSTCC
 /* Image format types, returned by _get_format() routine */
 #define IMAGE_FORMAT_INVALID	0x00
@@ -415,8 +422,71 @@
 int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 		uint8_t arch, ulong *rd_start, ulong *rd_end);
 
+/**
+ * fit_image_load() - load an image from a FIT
+ *
+ * This deals with all aspects of loading an image from a FIT, including
+ * selecting the right image based on configuration, verifying it, printing
+ * out progress messages, checking the type/arch/os and optionally copying it
+ * to the right load address.
+ *
+ * @param images	Boot images structure
+ * @param prop_name	Property name to look up (FIT_..._PROP)
+ * @param addr		Address of FIT in memory
+ * @param fit_unamep	On entry this is the requested image name
+ *			(e.g. "kernel@1") or NULL to use the default. On exit
+ *			points to the selected image name
+ * @param fit_uname_config	Requested configuration name, or NULL for the
+ *			default
+ * @param arch		Expected architecture (IH_ARCH_...)
+ * @param image_type	Required image type (IH_TYPE_...). If this is
+ *			IH_TYPE_KERNEL then we allow IH_TYPE_KERNEL_NOLOAD
+ *			also.
+ * @param bootstage_id	ID of starting bootstage to use for progress updates.
+ *			This will be added to the BOOTSTAGE_SUB values when
+ *			calling bootstage_mark()
+ * @param load_op	Decribes what to do with the load address
+ * @param datap		Returns address of loaded image
+ * @param lenp		Returns length of loaded image
+ */
+int fit_image_load(bootm_headers_t *images, const char *prop_name, ulong addr,
+		   const char **fit_unamep, const char *fit_uname_config,
+		   int arch, int image_type, int bootstage_id,
+		   enum fit_load_op load_op, ulong *datap, ulong *lenp);
+
-int boot_get_fdt(int flag, int argc, char * const argv[],
-		bootm_headers_t *images, char **of_flat_tree, ulong *of_size);
+/**
+ * fit_get_node_from_config() - Look up an image a FIT by type
+ *
+ * This looks in the selected conf@ node (images->fit_uname_cfg) for a
+ * particular image type (e.g. "kernel") and then finds the image that is
+ * referred to.
+ *
+ * For example, for something like:
+ *
+ * images {
+ *	kernel@1 {
+ *		...
+ *	};
+ * };
+ * configurations {
+ *	conf@1 {
+ *		kernel = "kernel@1";
+ *	};
+ * };
+ *
+ * the function will return the node offset of the kernel@1 node, assuming
+ * that conf@1 is the chosen configuration.
+ *
+ * @param images	Boot images structure
+ * @param prop_name	Property name to look up (FIT_..._PROP)
+ * @param addr		Address of FIT in memory
+ */
+int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name,
+			ulong addr);
+
+int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
+		 bootm_headers_t *images,
+		 char **of_flat_tree, ulong *of_size);
 void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob);
 int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size);
 
@@ -697,6 +767,7 @@
 int fit_add_verification_data(void *fit);
 
 int fit_image_verify(const void *fit, int noffset);
+int fit_config_verify(const void *fit, int conf_noffset);
 int fit_all_image_verify(const void *fit);
 int fit_image_check_os(const void *fit, int noffset, uint8_t os);
 int fit_image_check_arch(const void *fit, int noffset, uint8_t arch);
@@ -706,9 +777,6 @@
 
 int fit_conf_find_compat(const void *fit, const void *fdt);
 int fit_conf_get_node(const void *fit, const char *conf_uname);
-int fit_conf_get_kernel_node(const void *fit, int noffset);
-int fit_conf_get_ramdisk_node(const void *fit, int noffset);
-int fit_conf_get_fdt_node(const void *fit, int noffset);
 
 /**
  * fit_conf_get_prop_node() - Get node refered to by a configuration
@@ -732,12 +800,35 @@
 int calculate_hash(const void *data, int data_len, const char *algo,
 			uint8_t *value, int *value_len);
 
-#ifndef USE_HOSTCC
+/*
+ * At present we only support verification on the device
+ */
+#if defined(CONFIG_FIT_SIGNATURE)
+# ifdef USE_HOSTCC
+#  define IMAGE_ENABLE_VERIFY	0
+#else
+#  define IMAGE_ENABLE_VERIFY	1
+# endif
+#else
+# define IMAGE_ENABLE_VERIFY	0
+#endif
+
+#ifdef USE_HOSTCC
+# define gd_fdt_blob()		NULL
+#else
+# define gd_fdt_blob()		(gd->fdt_blob)
+#endif
+
+#ifdef CONFIG_FIT_BEST_MATCH
+#define IMAGE_ENABLE_BEST_MATCH	1
+#else
+#define IMAGE_ENABLE_BEST_MATCH	0
+#endif
+
 static inline int fit_image_check_target_arch(const void *fdt, int node)
 {
 	return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT);
 }
-#endif /* USE_HOSTCC */
 
 #ifdef CONFIG_FIT_VERBOSE
 #define fit_unsupported(msg)	printf("! %s:%d " \
diff --git a/include/net.h b/include/net.h
index 970d4d1..23fb947 100644
--- a/include/net.h
+++ b/include/net.h
@@ -695,6 +695,9 @@
 /* get a random source port */
 extern unsigned int random_port(void);
 
+/* Update U-Boot over TFTP */
+extern int update_tftp(ulong addr);
+
 /**********************************************************************/
 
 #endif /* __NET_H__ */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index ac1fe0b..005ad3d 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -66,6 +66,7 @@
 	COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
 	COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
 	COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"),
+	COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645-tpm"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
diff --git a/test/image/test-fit.py b/test/image/test-fit.py
new file mode 100755
index 0000000..c4e8211
--- /dev/null
+++ b/test/image/test-fit.py
@@ -0,0 +1,422 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2013, Google Inc.
+#
+# Sanity check of the FIT handling in U-Boot
+#
+# 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
+#
+# To run this:
+#
+# make O=sandbox sandbox_config
+# make O=sandbox
+# ./test/image/test-fit.py -u sandbox/u-boot
+
+import doctest
+from optparse import OptionParser
+import os
+import shutil
+import struct
+import sys
+import tempfile
+
+# The 'command' library in patman is convenient for running commands
+base_path = os.path.dirname(sys.argv[0])
+patman = os.path.join(base_path, '../../tools/patman')
+sys.path.append(patman)
+
+import command
+
+# Define a base ITS which we can adjust using % and a dictionary
+base_its = '''
+/dts-v1/;
+
+/ {
+        description = "Chrome OS kernel image with one or more FDT blobs";
+        #address-cells = <1>;
+
+        images {
+                kernel@1 {
+                        data = /incbin/("%(kernel)s");
+                        type = "kernel";
+                        arch = "sandbox";
+                        os = "linux";
+                        compression = "none";
+                        load = <0x40000>;
+                        entry = <0x8>;
+                };
+                fdt@1 {
+                        description = "snow";
+                        data = /incbin/("u-boot.dtb");
+                        type = "flat_dt";
+                        arch = "sandbox";
+                        %(fdt_load)s
+                        compression = "none";
+                        signature@1 {
+                                algo = "sha1,rsa2048";
+                                key-name-hint = "dev";
+                        };
+                };
+                ramdisk@1 {
+                        description = "snow";
+                        data = /incbin/("%(ramdisk)s");
+                        type = "ramdisk";
+                        arch = "sandbox";
+                        os = "linux";
+                        %(ramdisk_load)s
+                        compression = "none";
+                };
+        };
+        configurations {
+                default = "conf@1";
+                conf@1 {
+                        kernel = "kernel@1";
+                        fdt = "fdt@1";
+                        %(ramdisk_config)s
+                };
+        };
+};
+'''
+
+# Define a base FDT - currently we don't use anything in this
+base_fdt = '''
+/dts-v1/;
+
+/ {
+        model = "Sandbox Verified Boot Test";
+        compatible = "sandbox";
+
+};
+'''
+
+# This is the U-Boot script that is run for each test. First load the fit,
+# then do the 'bootm' command, then save out memory from the places where
+# we expect 'bootm' to write things. Then quit.
+base_script = '''
+sb load host 0 %(fit_addr)x %(fit)s
+fdt addr %(fit_addr)x
+bootm start %(fit_addr)x
+bootm loados
+sb save host 0 %(kernel_out)s %(kernel_addr)x %(kernel_size)x
+sb save host 0 %(fdt_out)s %(fdt_addr)x %(fdt_size)x
+sb save host 0 %(ramdisk_out)s %(ramdisk_addr)x %(ramdisk_size)x
+reset
+'''
+
+def make_fname(leaf):
+    """Make a temporary filename
+
+    Args:
+        leaf: Leaf name of file to create (within temporary directory)
+    Return:
+        Temporary filename
+    """
+    global base_dir
+
+    return os.path.join(base_dir, leaf)
+
+def filesize(fname):
+    """Get the size of a file
+
+    Args:
+        fname: Filename to check
+    Return:
+        Size of file in bytes
+    """
+    return os.stat(fname).st_size
+
+def read_file(fname):
+    """Read the contents of a file
+
+    Args:
+        fname: Filename to read
+    Returns:
+        Contents of file as a string
+    """
+    with open(fname, 'r') as fd:
+        return fd.read()
+
+def make_dtb():
+    """Make a sample .dts file and compile it to a .dtb
+
+    Returns:
+        Filename of .dtb file created
+    """
+    src = make_fname('u-boot.dts')
+    dtb = make_fname('u-boot.dtb')
+    with open(src, 'w') as fd:
+        print >>fd, base_fdt
+    command.Output('dtc', src, '-O', 'dtb', '-o', dtb)
+    return dtb
+
+def make_its(params):
+    """Make a sample .its file with parameters embedded
+
+    Args:
+        params: Dictionary containing parameters to embed in the %() strings
+    Returns:
+        Filename of .its file created
+    """
+    its = make_fname('test.its')
+    with open(its, 'w') as fd:
+        print >>fd, base_its % params
+    return its
+
+def make_fit(mkimage, params):
+    """Make a sample .fit file ready for loading
+
+    This creates a .its script with the selected parameters and uses mkimage to
+    turn this into a .fit image.
+
+    Args:
+        mkimage: Filename of 'mkimage' utility
+        params: Dictionary containing parameters to embed in the %() strings
+    Return:
+        Filename of .fit file created
+    """
+    fit = make_fname('test.fit')
+    its = make_its(params)
+    command.Output(mkimage, '-f', its, fit)
+    with open(make_fname('u-boot.dts'), 'w') as fd:
+        print >>fd, base_fdt
+    return fit
+
+def make_kernel():
+    """Make a sample kernel with test data
+
+    Returns:
+        Filename of kernel created
+    """
+    fname = make_fname('test-kernel.bin')
+    data = ''
+    for i in range(100):
+        data += 'this kernel %d is unlikely to boot\n' % i
+    with open(fname, 'w') as fd:
+        print >>fd, data
+    return fname
+
+def make_ramdisk():
+    """Make a sample ramdisk with test data
+
+    Returns:
+        Filename of ramdisk created
+    """
+    fname = make_fname('test-ramdisk.bin')
+    data = ''
+    for i in range(100):
+        data += 'ramdisk %d was seldom used in the middle ages\n' % i
+    with open(fname, 'w') as fd:
+        print >>fd, data
+    return fname
+
+def find_matching(text, match):
+    """Find a match in a line of text, and return the unmatched line portion
+
+    This is used to extract a part of a line from some text. The match string
+    is used to locate the line - we use the first line that contains that
+    match text.
+
+    Once we find a match, we discard the match string itself from the line,
+    and return what remains.
+
+    TODO: If this function becomes more generally useful, we could change it
+    to use regex and return groups.
+
+    Args:
+        text: Text to check (each line separated by \n)
+        match: String to search for
+    Return:
+        String containing unmatched portion of line
+    Exceptions:
+        ValueError: If match is not found
+
+    >>> find_matching('first line:10\\nsecond_line:20', 'first line:')
+    '10'
+    >>> find_matching('first line:10\\nsecond_line:20', 'second linex')
+    Traceback (most recent call last):
+      ...
+    ValueError: Test aborted
+    >>> find_matching('first line:10\\nsecond_line:20', 'second_line:')
+    '20'
+    """
+    for line in text.splitlines():
+        pos = line.find(match)
+        if pos != -1:
+            return line[:pos] + line[pos + len(match):]
+
+    print "Expected '%s' but not found in output:"
+    print text
+    raise ValueError('Test aborted')
+
+def set_test(name):
+    """Set the name of the current test and print a message
+
+    Args:
+        name: Name of test
+    """
+    global test_name
+
+    test_name = name
+    print name
+
+def fail(msg):
+    """Raise an error with a helpful failure message
+
+    Args:
+        msg: Message to display
+    """
+    raise ValueError("Test '%s' failed: %s" % (test_name, msg))
+
+def run_fit_test(mkimage, u_boot):
+    """Basic sanity check of FIT loading in U-Boot
+
+    TODO: Almost everything:
+       - hash algorithms - invalid hash/contents should be detected
+       - signature algorithms - invalid sig/contents should be detected
+       - compression
+       - checking that errors are detected like:
+            - image overwriting
+            - missing images
+            - invalid configurations
+            - incorrect os/arch/type fields
+            - empty data
+            - images too large/small
+            - invalid FDT (e.g. putting a random binary in instead)
+       - default configuration selection
+       - bootm command line parameters should have desired effect
+       - run code coverage to make sure we are testing all the code
+    """
+    global test_name
+
+    # Set up invariant files
+    control_dtb = make_dtb()
+    kernel = make_kernel()
+    ramdisk = make_ramdisk()
+    kernel_out = make_fname('kernel-out.bin')
+    fdt_out = make_fname('fdt-out.dtb')
+    ramdisk_out = make_fname('ramdisk-out.bin')
+
+    # Set up basic parameters with default values
+    params = {
+        'fit_addr' : 0x1000,
+
+        'kernel' : kernel,
+        'kernel_out' : kernel_out,
+        'kernel_addr' : 0x40000,
+        'kernel_size' : filesize(kernel),
+
+        'fdt_out' : fdt_out,
+        'fdt_addr' : 0x80000,
+        'fdt_size' : filesize(control_dtb),
+        'fdt_load' : '',
+
+        'ramdisk' : ramdisk,
+        'ramdisk_out' : ramdisk_out,
+        'ramdisk_addr' : 0xc0000,
+        'ramdisk_size' : filesize(ramdisk),
+        'ramdisk_load' : '',
+        'ramdisk_config' : '',
+    }
+
+    # Make a basic FIT and a script to load it
+    fit = make_fit(mkimage, params)
+    params['fit'] = fit
+    cmd = base_script % params
+
+    # First check that we can load a kernel
+    # We could perhaps reduce duplication with some loss of readability
+    set_test('Kernel load')
+    stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
+    if read_file(kernel) != read_file(kernel_out):
+        fail('Kernel not loaded')
+    if read_file(control_dtb) == read_file(fdt_out):
+        fail('FDT loaded but should be ignored')
+    if read_file(ramdisk) == read_file(ramdisk_out):
+        fail('Ramdisk loaded but should not be')
+
+    # Find out the offset in the FIT where U-Boot has found the FDT
+    line = find_matching(stdout, 'Booting using the fdt blob at ')
+    fit_offset = int(line, 16) - params['fit_addr']
+    fdt_magic = struct.pack('>L', 0xd00dfeed)
+    data = read_file(fit)
+
+    # Now find where it actually is in the FIT (skip the first word)
+    real_fit_offset = data.find(fdt_magic, 4)
+    if fit_offset != real_fit_offset:
+        fail('U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
+                (fit_offset, real_fit_offset))
+
+    # Now a kernel and an FDT
+    set_test('Kernel + FDT load')
+    params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr']
+    fit = make_fit(mkimage, params)
+    stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
+    if read_file(kernel) != read_file(kernel_out):
+        fail('Kernel not loaded')
+    if read_file(control_dtb) != read_file(fdt_out):
+        fail('FDT not loaded')
+    if read_file(ramdisk) == read_file(ramdisk_out):
+        fail('Ramdisk loaded but should not be')
+
+    # Try a ramdisk
+    set_test('Kernel + FDT + Ramdisk load')
+    params['ramdisk_config'] = 'ramdisk = "ramdisk@1";'
+    params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr']
+    fit = make_fit(mkimage, params)
+    stdout = command.Output(u_boot, '-d', control_dtb, '-c', cmd)
+    if read_file(ramdisk) != read_file(ramdisk_out):
+        fail('Ramdisk not loaded')
+
+def run_tests():
+    """Parse options, run the FIT tests and print the result"""
+    global base_path, base_dir
+
+    # Work in a temporary directory
+    base_dir = tempfile.mkdtemp()
+    parser = OptionParser()
+    parser.add_option('-u', '--u-boot',
+            default=os.path.join(base_path, 'u-boot'),
+            help='Select U-Boot sandbox binary')
+    parser.add_option('-k', '--keep', action='store_true',
+            help="Don't delete temporary directory even when tests pass")
+    parser.add_option('-t', '--selftest', action='store_true',
+            help='Run internal self tests')
+    (options, args) = parser.parse_args()
+
+    # Find the path to U-Boot, and assume mkimage is in its tools/mkimage dir
+    base_path = os.path.dirname(options.u_boot)
+    mkimage = os.path.join(base_path, 'tools/mkimage')
+
+    # There are a few doctests - handle these here
+    if options.selftest:
+        doctest.testmod()
+        return
+
+    title = 'FIT Tests'
+    print title, '\n', '=' * len(title)
+
+    run_fit_test(mkimage, options.u_boot)
+
+    print '\nTests passed'
+    print 'Caveat: this is only a sanity check - test coverage is poor'
+
+    # Remove the tempoerary directory unless we are asked to keep it
+    if options.keep:
+        print "Output files are in '%s'" % base_dir
+    else:
+        shutil.rmtree(base_dir)
+
+run_tests()
diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl
index 9f23901..896e2bc 100755
--- a/tools/checkpatch.pl
+++ b/tools/checkpatch.pl
@@ -273,6 +273,7 @@
 	WARN(?:_RATELIMIT|_ONCE|)|
 	panic|
 	debug|
+	printf|
 	MODULE_[A-Z_]+
 )};
 
diff --git a/tools/mkimage.h b/tools/mkimage.h
index e07a615..03c6c8f 100644
--- a/tools/mkimage.h
+++ b/tools/mkimage.h
@@ -44,12 +44,24 @@
 
 #define ARRAY_SIZE(x)		(sizeof(x) / sizeof((x)[0]))
 
+static inline void *map_sysmem(ulong paddr, unsigned long len)
+{
+	return (void *)(uintptr_t)paddr;
+}
+
+static inline ulong map_to_sysmem(void *ptr)
+{
+	return (ulong)(uintptr_t)ptr;
+}
+
 #define MKIMAGE_TMPFILE_SUFFIX		".tmp"
 #define MKIMAGE_MAX_TMPFILE_LEN		256
 #define MKIMAGE_DEFAULT_DTC_OPTIONS	"-I dts -O dtb -p 500"
 #define MKIMAGE_MAX_DTC_CMDLINE_LEN	512
 #define MKIMAGE_DTC			"dtc"   /* assume dtc is in $PATH */
 
+#define IH_ARCH_DEFAULT		IH_ARCH_INVALID
+
 /*
  * This structure defines all such variables those are initialized by
  * mkimage main core and need to be referred by image type specific