Merge branch 'master' of git://git.denx.de/u-boot-avr32
diff --git a/.travis.yml b/.travis.yml
index 90f0fd7..923c9dd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -107,9 +107,6 @@
         - TEST_CMD="tools/buildman/buildman mpc512x"
           INSTALL_TOOLCHAIN="ppc"
     - env:
-        - TEST_CMD="tools/buildman/buildman mpc824x"
-          INSTALL_TOOLCHAIN="ppc"
-    - env:
         - TEST_CMD="tools/buildman/buildman mpc8260"
           INSTALL_TOOLCHAIN="ppc"
     - env:
diff --git a/Makefile b/Makefile
index 6da4215..bd4abab 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2015
 PATCHLEVEL = 04
 SUBLEVEL =
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 NAME =
 
 # *DOCUMENTATION*
@@ -281,6 +281,11 @@
 HOSTCC       = $(call os_x_before, 10, 5, "cc", "gcc")
 HOSTCFLAGS  += $(call os_x_before, 10, 4, "-traditional-cpp")
 HOSTLDFLAGS += $(call os_x_before, 10, 5, "-multiply_defined suppress")
+
+# since Lion (10.7) ASLR is on by default, but we use linker generated lists
+# in some host tools which is a problem then ... so disable ASLR for these
+# tools
+HOSTLDFLAGS += $(call os_x_before, 10, 7, "", "-Xlinker -no_pie")
 endif
 
 # Decide whether to build built-in, modular, or both.
diff --git a/arch/arm/cpu/armv7/am33xx/clock_am43xx.c b/arch/arm/cpu/armv7/am33xx/clock_am43xx.c
index 31188c8..529a119 100644
--- a/arch/arm/cpu/armv7/am33xx/clock_am43xx.c
+++ b/arch/arm/cpu/armv7/am33xx/clock_am43xx.c
@@ -118,4 +118,7 @@
 
 	/* Select the Master osc clk as Timer2 clock source */
 	writel(0x1, &cmdpll->clktimer2clk);
+
+	/* For OPP100 the mac clock should be /5. */
+	writel(0x4, &cmdpll->clkselmacclk);
 }
diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c
index bc237c9..c7f943e 100644
--- a/arch/arm/cpu/armv7/exynos/spl_boot.c
+++ b/arch/arm/cpu/armv7/exynos/spl_boot.c
@@ -309,4 +309,3 @@
 	while (1)
 		;
 }
-void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {}
diff --git a/arch/arm/cpu/armv7/keystone/ddr3.c b/arch/arm/cpu/armv7/keystone/ddr3.c
index 923906a..dfb27b5 100644
--- a/arch/arm/cpu/armv7/keystone/ddr3.c
+++ b/arch/arm/cpu/armv7/keystone/ddr3.c
@@ -263,17 +263,14 @@
 }
 #endif
 
-void ddr3_init_ecc(u32 base)
+void ddr3_init_ecc(u32 base, u32 ddr3_size)
 {
-	u32 ddr3_size;
-
 	if (!ddr3_ecc_support_rmw(base)) {
 		ddr3_disable_ecc(base);
 		return;
 	}
 
 	ddr3_ecc_init_range(base);
-	ddr3_size = ddr3_get_size();
 	ddr3_reset_data(CONFIG_SYS_SDRAM_BASE, ddr3_size);
 
 	/* mapping DDR3 ECC system interrupt from CIC2 to GIC */
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index e601ba1..c01a98f 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -252,6 +252,8 @@
 {
 	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
 
+	writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
+	writel(regs->sdram_config_init, &emif->emif_sdram_config);
 	/*
 	 * Set SDRAM_CONFIG and PHY control registers to locked frequency
 	 * and RL =7. As the default values of the Mode Registers are not
@@ -265,7 +267,6 @@
 	writel(regs->sdram_tim2, &emif->emif_sdram_tim_2);
 	writel(regs->sdram_tim3, &emif->emif_sdram_tim_3);
 
-	writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
 	writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl);
 
 	/*
@@ -274,6 +275,7 @@
 	 */
 	if (is_dra7xx()) {
 		do_ext_phy_settings(base, regs);
+		writel(regs->ref_ctrl_final, &emif->emif_sdram_ref_ctrl);
 		writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
 		writel(regs->sdram_config_init, &emif->emif_sdram_config);
 	} else {
diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
index 86c0e42..e19c7ae 100644
--- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S
@@ -19,7 +19,7 @@
 ENTRY(save_boot_params)
 	ldr	r1, =OMAP_SRAM_SCRATCH_BOOT_PARAMS
 	str	r0, [r1]
-	bx	lr
+	b	save_boot_params_ret
 ENDPROC(save_boot_params)
 
 ENTRY(set_pl310_ctrl_reg)
diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
index 78577b1..80cb263 100644
--- a/arch/arm/cpu/armv7/omap3/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
@@ -23,7 +23,7 @@
 	ldr	r5, [r0, #0x4]
 	and	r5, r5, #0xff
 	str	r5, [r4]
-	bx	lr
+	b	save_boot_params_ret
 ENDPROC(save_boot_params)
 #endif
 
diff --git a/arch/arm/cpu/armv7/omap5/sdram.c b/arch/arm/cpu/armv7/omap5/sdram.c
index 7d8cec0..5f8daa1 100644
--- a/arch/arm/cpu/armv7/omap5/sdram.c
+++ b/arch/arm/cpu/armv7/omap5/sdram.c
@@ -141,7 +141,8 @@
 	.sdram_config_init              = 0x61851ab2,
 	.sdram_config                   = 0x61851ab2,
 	.sdram_config2			= 0x08000000,
-	.ref_ctrl                       = 0x00001035,
+	.ref_ctrl                       = 0x000040F1,
+	.ref_ctrl_final			= 0x00001035,
 	.sdram_tim1                     = 0xCCCF36B3,
 	.sdram_tim2                     = 0x308F7FDA,
 	.sdram_tim3                     = 0x027F88A8,
@@ -151,10 +152,10 @@
 	.emif_ddr_phy_ctlr_1_init       = 0x0E24400A,
 	.emif_ddr_phy_ctlr_1            = 0x0E24400A,
 	.emif_ddr_ext_phy_ctrl_1        = 0x10040100,
-	.emif_ddr_ext_phy_ctrl_2        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_3        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_4        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_5        = 0x00BB00BB,
+	.emif_ddr_ext_phy_ctrl_2        = 0x00910091,
+	.emif_ddr_ext_phy_ctrl_3        = 0x00950095,
+	.emif_ddr_ext_phy_ctrl_4        = 0x009B009B,
+	.emif_ddr_ext_phy_ctrl_5        = 0x009E009E,
 	.emif_rd_wr_lvl_rmp_win         = 0x00000000,
 	.emif_rd_wr_lvl_rmp_ctl         = 0x00000000,
 	.emif_rd_wr_lvl_ctl             = 0x00000000,
@@ -165,7 +166,8 @@
 	.sdram_config_init              = 0x61851B32,
 	.sdram_config                   = 0x61851B32,
 	.sdram_config2			= 0x08000000,
-	.ref_ctrl                       = 0x00001035,
+	.ref_ctrl                       = 0x000040F1,
+	.ref_ctrl_final			= 0x00001035,
 	.sdram_tim1                     = 0xCCCF36B3,
 	.sdram_tim2                     = 0x308F7FDA,
 	.sdram_tim3                     = 0x027F88A8,
@@ -175,10 +177,10 @@
 	.emif_ddr_phy_ctlr_1_init       = 0x0E24400A,
 	.emif_ddr_phy_ctlr_1            = 0x0E24400A,
 	.emif_ddr_ext_phy_ctrl_1        = 0x10040100,
-	.emif_ddr_ext_phy_ctrl_2        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_3        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_4        = 0x00BB00BB,
-	.emif_ddr_ext_phy_ctrl_5        = 0x00BB00BB,
+	.emif_ddr_ext_phy_ctrl_2        = 0x00910091,
+	.emif_ddr_ext_phy_ctrl_3        = 0x00950095,
+	.emif_ddr_ext_phy_ctrl_4        = 0x009B009B,
+	.emif_ddr_ext_phy_ctrl_5        = 0x009E009E,
 	.emif_rd_wr_lvl_rmp_win         = 0x00000000,
 	.emif_rd_wr_lvl_rmp_ctl         = 0x00000000,
 	.emif_rd_wr_lvl_ctl             = 0x00000000,
@@ -186,18 +188,19 @@
 };
 
 const struct emif_regs emif_1_regs_ddr3_666_mhz_1cs_dra_es1 = {
-	.sdram_config_init              = 0x61851AB2,
-	.sdram_config                   = 0x61851AB2,
+	.sdram_config_init              = 0x61862B32,
+	.sdram_config                   = 0x61862B32,
 	.sdram_config2			= 0x08000000,
-	.ref_ctrl                       = 0x00001035,
-	.sdram_tim1                     = 0xCCCF36B3,
-	.sdram_tim2                     = 0x308F7FDA,
-	.sdram_tim3                     = 0x027F88A8,
+	.ref_ctrl                       = 0x0000493E,
+	.ref_ctrl_final			= 0x0000144A,
+	.sdram_tim1                     = 0xD113781C,
+	.sdram_tim2                     = 0x308F7FE3,
+	.sdram_tim3                     = 0x009F86A8,
 	.read_idle_ctrl                 = 0x00050000,
 	.zq_config                      = 0x0007190B,
 	.temp_alert_config              = 0x00000000,
-	.emif_ddr_phy_ctlr_1_init       = 0x0024400A,
-	.emif_ddr_phy_ctlr_1            = 0x0024400A,
+	.emif_ddr_phy_ctlr_1_init       = 0x0E24400D,
+	.emif_ddr_phy_ctlr_1            = 0x0E24400D,
 	.emif_ddr_ext_phy_ctrl_1        = 0x10040100,
 	.emif_ddr_ext_phy_ctrl_2        = 0x00A400A4,
 	.emif_ddr_ext_phy_ctrl_3        = 0x00A900A9,
@@ -420,22 +423,22 @@
 
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
-	0x00BB00BB,
-	0x00440044,
-	0x00440044,
-	0x00440044,
-	0x00440044,
-	0x00440044,
+	0x00980098,
+	0x00340034,
+	0x00350035,
+	0x00340034,
+	0x00310031,
+	0x00340034,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
-	0x00600060,
-	0x00600060,
-	0x00600060,
-	0x00600060,
-	0x00600060,
+	0x00480048,
+	0x004A004A,
+	0x00520052,
+	0x00550055,
+	0x00500050,
 	0x00000000,
 	0x00600020,
 	0x40010080,
@@ -449,22 +452,22 @@
 
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
-	0x00BB00BB,
-	0x00440044,
-	0x00440044,
-	0x00440044,
-	0x00440044,
-	0x00440044,
+	0x00980098,
+	0x00330033,
+	0x00330033,
+	0x002F002F,
+	0x00320032,
+	0x00310031,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
 	0x007F007F,
-	0x00600060,
-	0x00600060,
-	0x00600060,
-	0x00600060,
-	0x00600060,
+	0x00520052,
+	0x00520052,
+	0x00470047,
+	0x00490049,
+	0x00500050,
 	0x00000000,
 	0x00600020,
 	0x40010080,
diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
index 70048c1..9b49ece 100644
--- a/arch/arm/cpu/armv7/start.S
+++ b/arch/arm/cpu/armv7/start.S
@@ -31,9 +31,12 @@
  *************************************************************************/
 
 	.globl	reset
+	.globl	save_boot_params_ret
 
 reset:
-	bl	save_boot_params
+	/* Allow the board to save important registers */
+	b	save_boot_params
+save_boot_params_ret:
 	/*
 	 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
 	 * except if in HYP mode already
@@ -96,7 +99,7 @@
  *
  *************************************************************************/
 ENTRY(save_boot_params)
-	bx	lr			@ back to my caller
+	b	save_boot_params_ret		@ back to my caller
 ENDPROC(save_boot_params)
 	.weak	save_boot_params
 
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 48db744..4bb12ad 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -11,6 +11,7 @@
 obj-y	+= board.o
 obj-y	+= clock.o
 obj-y	+= cpu_info.o
+obj-y	+= dram_helpers.o
 obj-y	+= pinmux.o
 obj-y	+= usbc.o
 obj-$(CONFIG_MACH_SUN6I)	+= prcm.o
@@ -38,7 +39,5 @@
 obj-$(CONFIG_MACH_SUN6I)	+= dram_sun6i.o
 obj-$(CONFIG_MACH_SUN7I)	+= dram_sun4i.o
 obj-$(CONFIG_MACH_SUN8I)	+= dram_sun8i.o
-ifdef CONFIG_SPL_FEL
-obj-y	+= start.o
-endif
+obj-y	+= fel_utils.o
 endif
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index 6e28bcd..c02c015 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -27,6 +27,17 @@
 
 #include <linux/compiler.h>
 
+struct fel_stash {
+	uint32_t sp;
+	uint32_t lr;
+	uint32_t cpsr;
+	uint32_t sctlr;
+	uint32_t vbar;
+	uint32_t cr;
+};
+
+struct fel_stash fel_stash __attribute__((section(".data")));
+
 static int gpio_init(void)
 {
 #if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
@@ -65,6 +76,12 @@
 	return 0;
 }
 
+void spl_board_load_image(void)
+{
+	debug("Returning to FEL sp=%x, lr=%x\n", fel_stash.sp, fel_stash.lr);
+	return_to_fel(fel_stash.sp, fel_stash.lr);
+}
+
 void s_init(void)
 {
 #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I
@@ -95,7 +112,34 @@
  */
 u32 spl_boot_device(void)
 {
-	return BOOT_DEVICE_MMC1;
+#ifdef CONFIG_SPL_FEL
+	/*
+	 * This is the legacy compile time configuration for a special FEL
+	 * enabled build. It has many restrictions and can only boot over USB.
+	 */
+	return BOOT_DEVICE_BOARD;
+#else
+	/*
+	 * When booting from the SD card, the "eGON.BT0" signature is expected
+	 * to be found in memory at the address 0x0004 (see the "mksunxiboot"
+	 * tool, which generates this header).
+	 *
+	 * When booting in the FEL mode over USB, this signature is patched in
+	 * memory and replaced with something else by the 'fel' tool. This other
+	 * signature is selected in such a way, that it can't be present in a
+	 * valid bootable SD card image (because the BROM would refuse to
+	 * execute the SPL in this case).
+	 *
+	 * This branch is just making a decision at runtime whether to load
+	 * the main u-boot binary from the SD card (if the "eGON.BT0" signature
+	 * is found) or return to the FEL code in the BROM to wait and receive
+	 * the main u-boot binary over USB.
+	 */
+	if (readl(4) == 0x4E4F4765 && readl(8) == 0x3054422E) /* eGON.BT0 */
+		return BOOT_DEVICE_MMC1;
+	else
+		return BOOT_DEVICE_BOARD;
+#endif
 }
 
 /* No confirmation data available in SPL yet. Hardcode bootmode */
diff --git a/arch/arm/cpu/armv7/sunxi/config.mk b/arch/arm/cpu/armv7/sunxi/config.mk
index 00f5ffc..76ffec9 100644
--- a/arch/arm/cpu/armv7/sunxi/config.mk
+++ b/arch/arm/cpu/armv7/sunxi/config.mk
@@ -1,8 +1,6 @@
 # Build a combined spl + u-boot image
 ifdef CONFIG_SPL
 ifndef CONFIG_SPL_BUILD
-ifndef CONFIG_SPL_FEL
 ALL-y += u-boot-sunxi-with-spl.bin
 endif
 endif
-endif
diff --git a/arch/arm/cpu/armv7/sunxi/dram_helpers.c b/arch/arm/cpu/armv7/sunxi/dram_helpers.c
new file mode 100644
index 0000000..9a94e1b
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/dram_helpers.c
@@ -0,0 +1,37 @@
+/*
+ * DRAM init helper functions
+ *
+ * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/dram.h>
+
+/*
+ * Wait up to 1s for value to be set in given part of reg.
+ */
+void mctl_await_completion(u32 *reg, u32 mask, u32 val)
+{
+	unsigned long tmo = timer_get_us() + 1000000;
+
+	while ((readl(reg) & mask) != val) {
+		if (timer_get_us() > tmo)
+			panic("Timeout initialising DRAM\n");
+	}
+}
+
+/*
+ * Test if memory at offset offset matches memory at begin of DRAM
+ */
+bool mctl_mem_matches(u32 offset)
+{
+	/* Try to write different values to RAM at two addresses */
+	writel(0, CONFIG_SYS_SDRAM_BASE);
+	writel(0xaa55aa55, CONFIG_SYS_SDRAM_BASE + offset);
+	/* Check if the same value is actually observed when reading back */
+	return readl(CONFIG_SYS_SDRAM_BASE) ==
+	       readl(CONFIG_SYS_SDRAM_BASE + offset);
+}
diff --git a/arch/arm/cpu/armv7/sunxi/fel_utils.S b/arch/arm/cpu/armv7/sunxi/fel_utils.S
new file mode 100644
index 0000000..bf00335
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/fel_utils.S
@@ -0,0 +1,42 @@
+/*
+ * Utility functions for FEL mode.
+ *
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/system.h>
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+	ldr	r0, =fel_stash
+	str	sp, [r0, #0]
+	str	lr, [r0, #4]
+	mrs	lr, cpsr		@ Read CPSR
+	str	lr, [r0, #8]
+	mrc	p15, 0, lr, c1, c0, 0	@ Read CP15 SCTLR Register
+	str	lr, [r0, #12]
+	mrc	p15, 0, lr, c12, c0, 0	@ Read VBAR
+	str	lr, [r0, #16]
+	mrc	p15, 0, lr, c1, c0, 0	@ Read CP15 Control Register
+	str	lr, [r0, #20]
+	b	save_boot_params_ret
+ENDPROC(save_boot_params)
+
+ENTRY(return_to_fel)
+	mov	sp, r0
+	mov	lr, r1
+	ldr	r0, =fel_stash
+	ldr	r1, [r0, #20]
+	mcr	p15, 0, r1, c1, c0, 0	@ Write CP15 Control Register
+	ldr	r1, [r0, #16]
+	mcr	p15, 0, r1, c12, c0, 0	@ Write VBAR
+	ldr	r1, [r0, #12]
+	mcr	p15, 0, r1, c1, c0, 0	@ Write CP15 SCTLR Register
+	ldr	r1, [r0, #8]
+	msr	cpsr, r1		@ Write CPSR
+	bx	lr
+ENDPROC(return_to_fel)
diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
deleted file mode 100644
index 928b7c1..0000000
--- a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * (C) Copyright 2013
- * Henrik Nordstrom <henrik@henriknordstrom.net>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(s_init)
-SECTIONS
-{
-	. = 0x00002000;
-
-	. = ALIGN(4);
-	.text :
-	{
-		*(.text.s_init)
-		*(.text*)
-	}
-
-	. = ALIGN(4);
-	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
-
-	. = ALIGN(4);
-	.data : {
-		*(.data*)
-	}
-
-	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
-	}
-
-	. = ALIGN(4);
-	. = .;
-
-	. = ALIGN(4);
-	.rel.dyn : {
-		__rel_dyn_start = .;
-		*(.rel*)
-		__rel_dyn_end = .;
-	}
-
-	.dynsym : {
-		__dynsym_start = .;
-		*(.dynsym)
-	}
-
-	. = ALIGN(4);
-	.note.gnu.build-id :
-	{
-		*(.note.gnu.build-id)
-	}
-	_end = .;
-
-	. = ALIGN(4096);
-	.mmutable : {
-		*(.mmutable)
-	}
-
-	.bss_start __rel_dyn_start (OVERLAY) : {
-		KEEP(*(.__bss_start));
-		__bss_base = .;
-	}
-
-	.bss __bss_base (OVERLAY) : {
-		*(.bss*)
-		. = ALIGN(4);
-		__bss_limit = .;
-	}
-
-	.bss_end __bss_limit (OVERLAY) : {
-		KEEP(*(.__bss_end));
-	}
-
-	/DISCARD/ : { *(.dynstr*) }
-	/DISCARD/ : { *(.dynamic*) }
-	/DISCARD/ : { *(.plt*) }
-	/DISCARD/ : { *(.interp*) }
-	/DISCARD/ : { *(.gnu*) }
-	/DISCARD/ : { *(.note*) }
-}
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index b94b56c..523d22e 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -400,6 +400,8 @@
 struct cm_dpll {
 	unsigned int resv1;
 	unsigned int clktimer2clk;	/* offset 0x04 */
+	unsigned int resv2[11];
+	unsigned int clkselmacclk;	/* offset 0x34 */ 
 };
 #endif /* CONFIG_AM43XX */
 
diff --git a/arch/arm/include/asm/arch-keystone/ddr3.h b/arch/arm/include/asm/arch-keystone/ddr3.h
index b044d6f..a22c237 100644
--- a/arch/arm/include/asm/arch-keystone/ddr3.h
+++ b/arch/arm/include/asm/arch-keystone/ddr3.h
@@ -48,10 +48,9 @@
 	unsigned int sdrfc;
 };
 
-void ddr3_init(void);
-int ddr3_get_size(void);
+u32 ddr3_init(void);
 void ddr3_reset_ddrphy(void);
-void ddr3_init_ecc(u32 base);
+void ddr3_init_ecc(u32 base, u32 ddr3_size);
 void ddr3_disable_ecc(u32 base);
 void ddr3_check_ecc_int(u32 base);
 int ddr3_ecc_support_rmw(u32 base);
diff --git a/arch/arm/include/asm/arch-lpc32xx/config.h b/arch/arm/include/asm/arch-lpc32xx/config.h
index 8f6426b..564441c 100644
--- a/arch/arm/include/asm/arch-lpc32xx/config.h
+++ b/arch/arm/include/asm/arch-lpc32xx/config.h
@@ -1,7 +1,7 @@
 /*
  * Common definitions for LPC32XX board configurations
  *
- * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com>
+ * Copyright (C) 2011-2015 Vladimir Zapolskiy <vz@mleia.com>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -9,6 +9,8 @@
 #ifndef _LPC32XX_CONFIG_H
 #define _LPC32XX_CONFIG_H
 
+#define CONFIG_SYS_GENERIC_BOARD
+
 /* Basic CPU architecture */
 #define CONFIG_ARCH_CPU_INIT
 
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 7ff43e6..aedd194 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -25,31 +25,7 @@
 #endif
 
 unsigned long sunxi_dram_init(void);
-
-/*
- * Wait up to 1s for value to be set in given part of reg.
- */
-static inline void mctl_await_completion(u32 *reg, u32 mask, u32 val)
-{
-	unsigned long tmo = timer_get_us() + 1000000;
-
-	while ((readl(reg) & mask) != val) {
-		if (timer_get_us() > tmo)
-			panic("Timeout initialising DRAM\n");
-	}
-}
-
-/*
- * Test if memory at offset offset matches memory at begin of DRAM
- */
-static inline bool mctl_mem_matches(u32 offset)
-{
-	/* Try to write different values to RAM at two addresses */
-	writel(0, CONFIG_SYS_SDRAM_BASE);
-	writel(0xaa55aa55, CONFIG_SYS_SDRAM_BASE + offset);
-	/* Check if the same value is actually observed when reading back */
-	return readl(CONFIG_SYS_SDRAM_BASE) ==
-	       readl(CONFIG_SYS_SDRAM_BASE + offset);
-}
+void mctl_await_completion(u32 *reg, u32 mask, u32 val);
+bool mctl_mem_matches(u32 offset);
 
 #endif /* _SUNXI_DRAM_H */
diff --git a/arch/arm/include/asm/arch-sunxi/sys_proto.h b/arch/arm/include/asm/arch-sunxi/sys_proto.h
index c3e636e..60a5bd8 100644
--- a/arch/arm/include/asm/arch-sunxi/sys_proto.h
+++ b/arch/arm/include/asm/arch-sunxi/sys_proto.h
@@ -13,4 +13,14 @@
 
 void sdelay(unsigned long);
 
+/* return_to_fel() - Return to BROM from SPL
+ *
+ * This returns back into the BROM after U-Boot SPL has performed its initial
+ * init. It uses the provided lr and sp to do so.
+ *
+ * @lr:		BROM link register value (return address)
+ * @sp:		BROM stack pointer
+ */
+void return_to_fel(uint32_t lr, uint32_t sp);
+
 #endif
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index 342f045..7a545ea 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -1149,6 +1149,7 @@
 	u32 sdram_config;
 	u32 sdram_config2;
 	u32 ref_ctrl;
+	u32 ref_ctrl_final;
 	u32 sdram_tim1;
 	u32 sdram_tim2;
 	u32 sdram_tim3;
diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h
index 8acd7cd..17b6f54 100644
--- a/arch/arm/include/asm/spl.h
+++ b/arch/arm/include/asm/spl.h
@@ -26,10 +26,14 @@
 	BOOT_DEVICE_SPI,
 	BOOT_DEVICE_SATA,
 	BOOT_DEVICE_I2C,
+	BOOT_DEVICE_BOARD,
 	BOOT_DEVICE_NONE
 };
 #endif
 
+/* Board-specific load method */
+void spl_board_load_image(void);
+
 /* Linker symbols. */
 extern char __bss_start[], __bss_end[];
 
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 89f2294..7820486 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -142,6 +142,21 @@
 
 #ifndef __ASSEMBLY__
 
+/**
+ * save_boot_params() - Save boot parameters before starting reset sequence
+ *
+ * If you provide this function it will be called immediately U-Boot starts,
+ * both for SPL and U-Boot proper.
+ *
+ * All registers are unchanged from U-Boot entry. No registers need be
+ * preserved.
+ *
+ * This is not a normal C function. There is no stack. Return by branching to
+ * save_boot_params_ret.
+ *
+ * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3);
+ */
+
 #define isb() __asm__ __volatile__ ("" : : : "memory")
 
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
diff --git a/board/keymile/common/common.h b/board/keymile/common/common.h
index e075f46..dcfefc4 100644
--- a/board/keymile/common/common.h
+++ b/board/keymile/common/common.h
@@ -126,7 +126,8 @@
 #endif
 
 int ethernet_present(void);
-int ivm_read_eeprom(void);
+int ivm_read_eeprom(unsigned char *buf, int len);
+int ivm_analyze_eeprom(unsigned char *buf, int len);
 
 int trigger_fpga_config(void);
 int wait_for_fpga_config(void);
diff --git a/board/keymile/common/ivm.c b/board/keymile/common/ivm.c
index b6b19cc..42db542 100644
--- a/board/keymile/common/ivm.c
+++ b/board/keymile/common/ivm.c
@@ -10,6 +10,8 @@
 #include <i2c.h>
 #include "common.h"
 
+#define MAC_STR_SZ	20
+
 static int ivm_calc_crc(unsigned char *buf, int len)
 {
 	const unsigned short crc_tab[16] = {
@@ -185,45 +187,37 @@
 	return 0;
 }
 
-static int calculate_mac_offset(unsigned char *valbuf, unsigned char *buf,
+/* take care of the possible MAC address offset and the IVM content offset */
+static int process_mac(unsigned char *valbuf, unsigned char *buf,
 				int offset)
 {
+	unsigned char mac[6];
 	unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6];
 
-	if (offset == 0)
-		return 0;
+	/* use an intermediate buffer, to not change IVM content
+	 * MAC address is at offset 1
+	 */
+	memcpy(mac, buf+1, 6);
 
-	val += offset;
-	buf[4] = (val >> 16) & 0xff;
-	buf[5] = (val >> 8) & 0xff;
-	buf[6] = val & 0xff;
-	sprintf((char *)valbuf, "%pM", buf + 1);
+	if (offset) {
+		val += offset;
+		mac[3] = (val >> 16) & 0xff;
+		mac[4] = (val >> 8) & 0xff;
+		mac[5] = val & 0xff;
+	}
+
+	sprintf((char *)valbuf, "%pM", mac);
 	return 0;
 }
 
 static int ivm_analyze_block2(unsigned char *buf, int len)
 {
-	unsigned char	valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
+	unsigned char	valbuf[MAC_STR_SZ];
 	unsigned long	count;
 
 	/* IVM_MAC Adress begins at offset 1 */
 	sprintf((char *)valbuf, "%pM", buf + 1);
 	ivm_set_value("IVM_MacAddress", (char *)valbuf);
-	/* if an offset is defined, add it */
-	calculate_mac_offset(buf, valbuf, CONFIG_PIGGY_MAC_ADRESS_OFFSET);
-#ifdef MACH_TYPE_KM_KIRKWOOD
-	setenv((char *)"ethaddr", (char *)valbuf);
-#else
-	if (getenv("ethaddr") == NULL)
-		setenv((char *)"ethaddr", (char *)valbuf);
-#endif
-#ifdef CONFIG_KMVECT1
-/* KMVECT1 has two ethernet interfaces */
-	if (getenv("eth1addr") == NULL) {
-		calculate_mac_offset(buf, valbuf, 1);
-		setenv((char *)"eth1addr", (char *)valbuf);
-	}
-#endif
 	/* IVM_MacCount */
 	count = (buf[10] << 24) +
 		   (buf[11] << 16) +
@@ -236,7 +230,7 @@
 	return 0;
 }
 
-static int ivm_analyze_eeprom(unsigned char *buf, int len)
+int ivm_analyze_eeprom(unsigned char *buf, int len)
 {
 	unsigned short	val;
 	unsigned char	valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
@@ -296,21 +290,44 @@
 	return 0;
 }
 
-int ivm_read_eeprom(void)
+static int ivm_populate_env(unsigned char *buf, int len)
 {
-	uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+	unsigned char	*page2;
+	unsigned char	valbuf[MAC_STR_SZ];
+
+	/* do we have the page 2 filled ? if not return */
+	if (ivm_check_crc(buf, 2))
+		return 0;
+	page2 = &buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN*2];
+
+	/* if an offset is defined, add it */
+	process_mac(valbuf, page2, CONFIG_PIGGY_MAC_ADRESS_OFFSET);
+	if (getenv("ethaddr") == NULL)
+		setenv((char *)"ethaddr", (char *)valbuf);
+#ifdef CONFIG_KMVECT1
+/* KMVECT1 has two ethernet interfaces */
+	if (getenv("eth1addr") == NULL) {
+		process_mac(valbuf, page2, 1);
+		setenv((char *)"eth1addr", (char *)valbuf);
+	}
+#endif
+
+	return 0;
+}
+
+int ivm_read_eeprom(unsigned char *buf, int len)
+{
 	int ret;
 
 	i2c_set_bus_num(CONFIG_KM_IVM_BUS);
 	/* add deblocking here */
 	i2c_make_abort();
 
-	ret = i2c_read(CONFIG_SYS_IVM_EEPROM_ADR, 0, 1, i2c_buffer,
-		CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+	ret = i2c_read(CONFIG_SYS_IVM_EEPROM_ADR, 0, 1, buf, len);
 	if (ret != 0) {
 		printf("Error reading EEprom\n");
 		return -2;
 	}
 
-	return ivm_analyze_eeprom(i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+	return ivm_populate_env(buf, len);
 }
diff --git a/board/keymile/km82xx/km82xx.c b/board/keymile/km82xx/km82xx.c
index bf84676..c599b40 100644
--- a/board/keymile/km82xx/km82xx.c
+++ b/board/keymile/km82xx/km82xx.c
@@ -18,6 +18,8 @@
 #include <i2c.h>
 #include "../common/common.h"
 
+static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+
 /*
  * I/O Port configuration table
  *
@@ -393,9 +395,15 @@
 	return 0;
 }
 
+int misc_init_r(void)
+{
+	ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+	return 0;
+}
+
 int hush_init_var(void)
 {
-	ivm_read_eeprom();
+	ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 
diff --git a/board/keymile/km83xx/km83xx.c b/board/keymile/km83xx/km83xx.c
index 1da0dcb..89e9e1e 100644
--- a/board/keymile/km83xx/km83xx.c
+++ b/board/keymile/km83xx/km83xx.c
@@ -28,6 +28,8 @@
 
 #include "../common/common.h"
 
+static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+
 const qe_iop_conf_t qe_iop_conf_tab[] = {
 	/* port pin dir open_drain assign */
 #if defined(CONFIG_MPC8360)
@@ -190,6 +192,7 @@
 
 int misc_init_r(void)
 {
+	ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 
@@ -370,7 +373,7 @@
 #if defined(CONFIG_HUSH_INIT_VAR)
 int hush_init_var(void)
 {
-	ivm_read_eeprom();
+	ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 #endif
diff --git a/board/keymile/km_arm/km_arm.c b/board/keymile/km_arm/km_arm.c
index 1c7c108..2938861 100644
--- a/board/keymile/km_arm/km_arm.c
+++ b/board/keymile/km_arm/km_arm.c
@@ -102,6 +102,8 @@
 	0
 };
 
+static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+
 #if defined(CONFIG_KM_MGCOGE3UN)
 /*
  * Wait for startup OK from mgcoge3ne
@@ -210,6 +212,8 @@
 	}
 #endif
 
+	ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+
 	initialize_unit_leds();
 	set_km_env();
 	set_bootcount_addr();
@@ -419,7 +423,7 @@
 #if defined(CONFIG_HUSH_INIT_VAR)
 int hush_init_var(void)
 {
-	ivm_read_eeprom();
+	ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 #endif
diff --git a/board/keymile/kmp204x/kmp204x.c b/board/keymile/kmp204x/kmp204x.c
index a74f75b..eebb47f 100644
--- a/board/keymile/kmp204x/kmp204x.c
+++ b/board/keymile/kmp204x/kmp204x.c
@@ -26,6 +26,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
+
 int checkboard(void)
 {
 	printf("Board: Keymile %s\n", CONFIG_KM_BOARD_NAME);
@@ -195,13 +197,14 @@
 		}
 	}
 
+	ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 
 #if defined(CONFIG_HUSH_INIT_VAR)
 int hush_init_var(void)
 {
-	ivm_read_eeprom();
+	ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
 	return 0;
 }
 #endif
diff --git a/board/nokia/rx51/lowlevel_init.S b/board/nokia/rx51/lowlevel_init.S
index e252909..9d4ea1b 100644
--- a/board/nokia/rx51/lowlevel_init.S
+++ b/board/nokia/rx51/lowlevel_init.S
@@ -37,7 +37,8 @@
 
 .global save_boot_params
 save_boot_params:
-
+	/* Get return address */
+	ldr	lr, =save_boot_params_ret
 
 /* Copy valid attached kernel to address KERNEL_ADDRESS */
 
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index 4a21589..3eab81f 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -149,6 +149,16 @@
 	bool "SPL/FEL mode support"
 	depends on SPL
 	default n
+	help
+	  This enables support for Fast Early Loader (FEL) mode. This
+	  allows U-Boot to be loaded to the board over USB by the on-chip
+	  boot rom. U-Boot should be sent in two parts: SPL first, with
+	  'fel write 0x2000 u-boot-spl.bin; fel exe 0x2000' then U-Boot with
+	  'fel write 0x4a000000 u-boot.bin; fel exe 0x4a000000'. This option
+	  shrinks the amount of SRAM available to SPL, so only enable it if
+	  you need FEL. Note that enabling this option only allows FEL to be
+	  used; it is still possible to boot U-Boot from boot media. U-Boot
+	  SPL detects when it is being loaded using FEL.
 
 config UART0_PORT_F
 	bool "UART0 on MicroSD breakout board"
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index faa413c..9a287d3 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -46,6 +46,11 @@
 F:	board/sunxi/dram_a20_olinuxino_l2.c
 F:	configs/A20-OLinuXino-Lime2_defconfig
 
+AMPE A76 BOARD
+M:	Paul Kocialkowski <contact@paulk.fr>
+S:	Maintained
+F:	configs/Ampe_A76_defconfig
+
 COLOMBUS BOARD
 M:	Maxime Ripard <maxime.ripard@free-electrons.com>
 S:	Maintained
@@ -57,9 +62,7 @@
 S:	Maintained
 F:	include/configs/sun7i.h
 F:	configs/Cubieboard2_defconfig
-F:	configs/Cubieboard2_FEL_defconfig
 F:	configs/Cubietruck_defconfig
-F:	configs/Cubietruck_FEL_defconfig
 
 GEMEI-G9 TABLET
 M:	Priit Laes <plaes@plaes.org>
diff --git a/board/ti/beagle_x15/board.c b/board/ti/beagle_x15/board.c
index db96e34..3a7e04d 100644
--- a/board/ti/beagle_x15/board.c
+++ b/board/ti/beagle_x15/board.c
@@ -47,7 +47,8 @@
 	.sdram_config_init	= 0x61851b32,
 	.sdram_config		= 0x61851b32,
 	.sdram_config2		= 0x00000000,
-	.ref_ctrl		= 0x00001035,
+	.ref_ctrl		= 0x000040F1,
+	.ref_ctrl_final		= 0x00001035,
 	.sdram_tim1		= 0xceef266b,
 	.sdram_tim2		= 0x328f7fda,
 	.sdram_tim3		= 0x027f88a8,
@@ -103,7 +104,8 @@
 	.sdram_config_init	= 0x61851b32,
 	.sdram_config		= 0x61851b32,
 	.sdram_config2		= 0x00000000,
-	.ref_ctrl		= 0x00001035,
+	.ref_ctrl		= 0x000040F1,
+	.ref_ctrl_final		= 0x00001035,
 	.sdram_tim1		= 0xceef266b,
 	.sdram_tim2		= 0x328f7fda,
 	.sdram_tim3		= 0x027f88a8,
diff --git a/board/ti/ks2_evm/board.c b/board/ti/ks2_evm/board.c
index 04ec675..8892a28 100644
--- a/board/ti/ks2_evm/board.c
+++ b/board/ti/ks2_evm/board.c
@@ -35,12 +35,14 @@
 
 int dram_init(void)
 {
-	ddr3_init();
+	u32 ddr3_size;
+
+	ddr3_size = ddr3_init();
 
 	gd->ram_size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
 				    CONFIG_MAX_RAM_BANK_SIZE);
 	aemif_init(ARRAY_SIZE(aemif_configs), aemif_configs);
-	ddr3_init_ecc(KS2_DDR3A_EMIF_CTRL_BASE);
+	ddr3_init_ecc(KS2_DDR3A_EMIF_CTRL_BASE, ddr3_size);
 	return 0;
 }
 
diff --git a/board/ti/ks2_evm/ddr3_k2e.c b/board/ti/ks2_evm/ddr3_k2e.c
index 40fd966..35ffb42 100644
--- a/board/ti/ks2_evm/ddr3_k2e.c
+++ b/board/ti/ks2_evm/ddr3_k2e.c
@@ -11,11 +11,11 @@
 #include "ddr3_cfg.h"
 #include <asm/arch/ddr3.h>
 
-static int ddr3_size;
 static struct pll_init_data ddr3_400 = DDR3_PLL_400;
 
-void ddr3_init(void)
+u32 ddr3_init(void)
 {
+	u32 ddr3_size;
 	char dimm_name[32];
 
 	if (~(readl(KS2_PLL_CNTRL_BASE + KS2_RSTCTRL_RSTYPE) & 0x1))
@@ -43,13 +43,11 @@
 		printf("DRAM: 4 GiB\n");
 		ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_4g);
 		ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_1600_4g);
+	} else {
+		printf("Unknown SO-DIMM. Cannot configure DDR3\n");
+		while (1)
+			;
 	}
-}
 
-/**
- * ddr3_get_size - return ddr3 size in GiB
- */
-int ddr3_get_size(void)
-{
 	return ddr3_size;
 }
diff --git a/board/ti/ks2_evm/ddr3_k2hk.c b/board/ti/ks2_evm/ddr3_k2hk.c
index a1c3d05..b36eb27 100644
--- a/board/ti/ks2_evm/ddr3_k2hk.c
+++ b/board/ti/ks2_evm/ddr3_k2hk.c
@@ -12,14 +12,13 @@
 #include <asm/arch/ddr3.h>
 #include <asm/arch/hardware.h>
 
-static int ddr3_size;
-
 struct pll_init_data ddr3a_333 = DDR3_PLL_333(A);
 struct pll_init_data ddr3a_400 = DDR3_PLL_400(A);
 
-void ddr3_init(void)
+u32 ddr3_init(void)
 {
 	char dimm_name[32];
+	u32 ddr3_size;
 
 	ddr3_get_dimm_params(dimm_name);
 
@@ -93,12 +92,6 @@
 	/* Apply the workaround for PG 1.0 and 1.1 Silicons */
 	if (cpu_revision() <= 1)
 		ddr3_err_reset_workaround();
-}
 
-/**
- * ddr3_get_size - return ddr3 size in GiB
- */
-int ddr3_get_size(void)
-{
 	return ddr3_size;
 }
diff --git a/board/ti/ks2_evm/ddr3_k2l.c b/board/ti/ks2_evm/ddr3_k2l.c
index 15a14f2..00fc194 100644
--- a/board/ti/ks2_evm/ddr3_k2l.c
+++ b/board/ti/ks2_evm/ddr3_k2l.c
@@ -11,28 +11,20 @@
 #include "ddr3_cfg.h"
 #include <asm/arch/ddr3.h>
 
-static int ddr3_size;
 static struct pll_init_data ddr3_400 = DDR3_PLL_400;
 
-void ddr3_init(void)
+u32 ddr3_init(void)
 {
 	init_pll(&ddr3_400);
 
 	/* No SO-DIMM, 2GB discreet DDR */
 	printf("DRAM: 2 GiB\n");
-	ddr3_size = 2;
 
 	/* Reset DDR3 PHY after PLL enabled */
 	ddr3_reset_ddrphy();
 
 	ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_2g);
 	ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE, &ddr3_1600_2g);
-}
 
-/**
- * ddr3_get_size - return ddr3 size in GiB
- */
-int ddr3_get_size(void)
-{
-	return ddr3_size;
+	return 2;
 }
diff --git a/common/image-fit.c b/common/image-fit.c
index b47d110..778d2a1 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1010,9 +1010,7 @@
 	}
 
 	/* Process all hash subnodes of the component image node */
-	for (noffset = fdt_first_subnode(fit, image_noffset);
-	     noffset >= 0;
-	     noffset = fdt_next_subnode(fit, noffset)) {
+	fdt_for_each_subnode(fit, noffset, image_noffset) {
 		const char *name = fit_get_name(fit, noffset, NULL);
 
 		/*
diff --git a/common/image-sig.c b/common/image-sig.c
index 2c9f0cd..eda5e13 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -212,9 +212,7 @@
 	int ret;
 
 	/* Process all hash subnodes of the component image node */
-	for (noffset = fdt_first_subnode(fit, image_noffset);
-	     noffset >= 0;
-	     noffset = fdt_next_subnode(fit, noffset)) {
+	fdt_for_each_subnode(fit, noffset, image_noffset) {
 		const char *name = fit_get_name(fit, noffset, NULL);
 
 		if (!strncmp(name, FIT_SIG_NODENAME,
@@ -262,9 +260,7 @@
 		return 0;
 	}
 
-	for (noffset = fdt_first_subnode(sig_blob, sig_node);
-	     noffset >= 0;
-	     noffset = fdt_next_subnode(sig_blob, noffset)) {
+	fdt_for_each_subnode(sig_blob, noffset, sig_node) {
 		const char *required;
 		int ret;
 
@@ -397,9 +393,7 @@
 	int ret;
 
 	/* Process all hash subnodes of the component conf node */
-	for (noffset = fdt_first_subnode(fit, conf_noffset);
-	     noffset >= 0;
-	     noffset = fdt_next_subnode(fit, noffset)) {
+	fdt_for_each_subnode(fit, noffset, conf_noffset) {
 		const char *name = fit_get_name(fit, noffset, NULL);
 
 		if (!strncmp(name, FIT_SIG_NODENAME,
@@ -444,9 +438,7 @@
 		return 0;
 	}
 
-	for (noffset = fdt_first_subnode(sig_blob, sig_node);
-	     noffset >= 0;
-	     noffset = fdt_next_subnode(sig_blob, noffset)) {
+	fdt_for_each_subnode(sig_blob, noffset, sig_node) {
 		const char *required;
 		int ret;
 
diff --git a/common/spl/spl.c b/common/spl/spl.c
index daaeb50..ded0f30 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -229,6 +229,11 @@
 		spl_sata_load_image();
 		break;
 #endif
+#ifdef CONFIG_SPL_BOARD_LOAD_IMAGE
+	case BOOT_DEVICE_BOARD:
+		spl_board_load_image();
+		break;
+#endif
 	default:
 #if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 		puts("SPL: Unsupported Boot Device!\n");
diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c
index 2c0e8e0..c2fee01 100644
--- a/common/spl/spl_nor.c
+++ b/common/spl/spl_nor.c
@@ -17,7 +17,7 @@
 
 #ifdef CONFIG_SPL_OS_BOOT
 	if (!spl_start_uboot()) {
-		struct image_header *header;
+		const struct image_header *header;
 
 		/*
 		 * Load Linux from its location in NOR flash to its defined
diff --git a/configs/Ampe_A76_defconfig b/configs/Ampe_A76_defconfig
new file mode 100644
index 0000000..2054fc3
--- /dev/null
+++ b/configs/Ampe_A76_defconfig
@@ -0,0 +1,15 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=2,AXP209_POWER"
+CONFIG_FDTFILE="sun5i-a13-ampe-a76.dtb"
+CONFIG_USB_MUSB_SUNXI=y
+CONFIG_USB0_VBUS_PIN="PG12"
+CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:45,ri:82,up:22,lo:22,hs:1,vs:1,sync:3,vmode:0"
+CONFIG_VIDEO_LCD_POWER="AXP0-0"
+CONFIG_VIDEO_LCD_BL_EN="AXP0-1"
+CONFIG_VIDEO_LCD_BL_PWM="PB2"
++S:CONFIG_ARM=y
++S:CONFIG_ARCH_SUNXI=y
++S:CONFIG_MACH_SUN5I=y
++S:CONFIG_DRAM_CLK=432
++S:CONFIG_DRAM_ZQ=123
++S:CONFIG_DRAM_EMR1=4
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index fc64f48..24123fc 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -989,12 +989,15 @@
 	if (err)
 		return err;
 
-#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
 	/* TODO: Implement for 16-bit bus width */
 	if (nand->options & NAND_BUSWIDTH_16)
 		nand->read_buf = nand_read_buf16;
+#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
 	else
 		nand->read_buf = omap_nand_read_prefetch8;
+#else
+	else
+		nand->read_buf = nand_read_buf;
 #endif
 
 	nand->dev_ready = omap_dev_ready;
diff --git a/drivers/net/keystone_net.c b/drivers/net/keystone_net.c
index bedab1d..35f1a57 100644
--- a/drivers/net/keystone_net.c
+++ b/drivers/net/keystone_net.c
@@ -398,8 +398,6 @@
 	sys_has_mdio =
 		(eth_priv->sgmii_link_type == SGMII_LINK_MAC_PHY) ? 1 : 0;
 
-	keystone2_net_serdes_setup();
-
 	if (sys_has_mdio)
 		keystone2_mdio_reset(mdio_bus);
 
@@ -556,6 +554,8 @@
 			return res;
 	}
 
+	keystone2_net_serdes_setup();
+
 	/* Create phy device and bind it with driver */
 #ifdef CONFIG_KSNET_MDIO_PHY_CONFIG_ENABLE
 	phy_dev = phy_connect(mdio_bus, eth_priv->phy_addr,
diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index ed92857..378efbf 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -223,9 +223,12 @@
 	struct pci_region *pci_mem = hose->pci_mem;
 	struct pci_region *pci_prefetch = hose->pci_prefetch;
 	struct pci_region *pci_io = hose->pci_io;
-	u16 cmdstat;
+	u16 cmdstat, prefechable_64;
 
 	pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
+	pci_hose_read_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
+				&prefechable_64);
+	prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
 
 	/* Configure bus number registers */
 	pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS,
@@ -252,12 +255,26 @@
 		/* Set up memory and I/O filter limits, assume 32-bit I/O space */
 		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE,
 					(pci_prefetch->bus_lower & 0xfff00000) >> 16);
+		if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
+#ifdef CONFIG_SYS_PCI_64BIT
+			pci_hose_write_config_dword(hose, dev,
+					PCI_PREF_BASE_UPPER32,
+					pci_prefetch->bus_lower >> 32);
+#else
+			pci_hose_write_config_dword(hose, dev,
+					PCI_PREF_BASE_UPPER32,
+					0x0);
+#endif
 
 		cmdstat |= PCI_COMMAND_MEMORY;
 	} else {
 		/* We don't support prefetchable memory for now, so disable */
 		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000);
 		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x0);
+		if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) {
+			pci_hose_write_config_word(hose, dev, PCI_PREF_BASE_UPPER32, 0x0);
+			pci_hose_write_config_word(hose, dev, PCI_PREF_LIMIT_UPPER32, 0x0);
+		}
 	}
 
 	if (pci_io) {
@@ -297,11 +314,28 @@
 	}
 
 	if (pci_prefetch) {
+		u16 prefechable_64;
+
+		pci_hose_read_config_word(hose, dev,
+					PCI_PREF_MEMORY_LIMIT,
+					&prefechable_64);
+		prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK;
+
 		/* Round memory allocator to 1MB boundary */
 		pciauto_region_align(pci_prefetch, 0x100000);
 
 		pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT,
 				(pci_prefetch->bus_lower - 1) >> 16);
+		if (prefechable_64 == PCI_PREF_RANGE_TYPE_64)
+#ifdef CONFIG_SYS_PCI_64BIT
+			pci_hose_write_config_dword(hose, dev,
+					PCI_PREF_LIMIT_UPPER32,
+					(pci_prefetch->bus_lower - 1) >> 32);
+#else
+			pci_hose_write_config_dword(hose, dev,
+					PCI_PREF_LIMIT_UPPER32,
+					0x0);
+#endif
 	}
 
 	if (pci_io) {
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 778916d..4646a3d 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -145,16 +145,6 @@
 	musb_writel(base, USBC_REG_o_ISCR, reg_val);
 }
 
-static void USBC_ForceVbusValidDisable(__iomem void *base)
-{
-	u32 reg_val;
-
-	reg_val = musb_readl(base, USBC_REG_o_ISCR);
-	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
-	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
-	musb_writel(base, USBC_REG_o_ISCR, reg_val);
-}
-
 static void USBC_ForceVbusValidToHigh(__iomem void *base)
 {
 	u32 reg_val;
@@ -248,12 +238,11 @@
 	if (is_host_enabled(musb)) {
 		/* Host mode */
 		USBC_ForceIdToLow(musb->mregs);
-		USBC_ForceVbusValidToHigh(musb->mregs);
 	} else {
 		/* Peripheral mode */
 		USBC_ForceIdToHigh(musb->mregs);
-		USBC_ForceVbusValidDisable(musb->mregs);
 	}
+	USBC_ForceVbusValidToHigh(musb->mregs);
 
 	return 0;
 }
diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c
index f5f24fc..dbda97e 100644
--- a/drivers/video/sunxi_display.c
+++ b/drivers/video/sunxi_display.c
@@ -46,6 +46,7 @@
 	GraphicDevice graphic_device;
 	enum sunxi_monitor monitor;
 	unsigned int depth;
+	unsigned int fb_size;
 } sunxi_display;
 
 #ifdef CONFIG_VIDEO_HDMI
@@ -1060,6 +1061,11 @@
 	return NULL; /* never reached */
 }
 
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
+}
+
 void *video_hw_init(void)
 {
 	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
@@ -1075,10 +1081,6 @@
 
 	memset(&sunxi_display, 0, sizeof(struct sunxi_display));
 
-	printf("Reserved %dkB of RAM for Framebuffer.\n",
-	       CONFIG_SUNXI_FB_SIZE >> 10);
-	gd->fb_base = gd->ram_top;
-
 	video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
 				 &sunxi_display.depth, &options);
 #ifdef CONFIG_VIDEO_HDMI
@@ -1169,6 +1171,17 @@
 		       mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
 	}
 
+	sunxi_display.fb_size =
+		(mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
+	if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
+		printf("Error need %dkB for fb, but only %dkB is reserved\n",
+		       sunxi_display.fb_size >> 10,
+		       CONFIG_SUNXI_MAX_FB_SIZE >> 10);
+		return NULL;
+	}
+
+	gd->fb_base = gd->bd->bi_dram[0].start +
+		      gd->bd->bi_dram[0].size - sunxi_display.fb_size;
 	sunxi_engines_init();
 	sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
 
@@ -1194,6 +1207,7 @@
 {
 	static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
 	int offset, ret;
+	u64 start, size;
 	const char *pipeline = NULL;
 
 #ifdef CONFIG_MACH_SUN4I
@@ -1237,6 +1251,20 @@
 		return 0; /* Keep older kernels working */
 	}
 
+	/*
+	 * Do not report the framebuffer as free RAM to the OS, note we cannot
+	 * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
+	 * and e.g. Linux refuses to iomap RAM on ARM, see:
+	 * linux/arch/arm/mm/ioremap.c around line 301.
+	 */
+	start = gd->bd->bi_dram[0].start;
+	size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
+	ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
+	if (ret) {
+		eprintf("Cannot setup simplefb: Error reserving memory\n");
+		return ret;
+	}
+
 	ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base,
 			graphic_device->winSizeX, graphic_device->winSizeY,
 			graphic_device->winSizeX * graphic_device->gdfBytesPP,
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index 49674f4..07a0b3b 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -10,6 +10,10 @@
 #ifndef _CONFIG_CMD_DISTRO_BOOTCMD_H
 #define _CONFIG_CMD_DISTRO_BOOTCMD_H
 
+/* We need the part command */
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_CMD_PART
+
 #define BOOTENV_SHARED_BLKDEV_BODY(devtypel) \
 		"if " #devtypel " dev ${devnum}; then " \
 			"setenv devtype " #devtypel "; " \
diff --git a/include/configs/km82xx.h b/include/configs/km82xx.h
index 14fd290..12f9d42 100644
--- a/include/configs/km82xx.h
+++ b/include/configs/km82xx.h
@@ -34,6 +34,8 @@
 
 #define	CONFIG_SYS_TEXT_BASE	0xFE000000
 
+#define CONFIG_MISC_INIT_R
+
 /* include common defines/options for all Keymile boards */
 #include "km/keymile-common.h"
 #include "km/km-powerpc.h"
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 09889ee..1238d82 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -18,10 +18,8 @@
  */
 #define CONFIG_SUNXI		/* sunxi family */
 #ifdef CONFIG_SPL_BUILD
-#ifndef CONFIG_SPL_FEL
 #define CONFIG_SYS_THUMB_BUILD	/* Thumbs mode to save space in SPL */
 #endif
-#endif
 
 #include <asm/arch/cpu.h>	/* get chip and board defs */
 
@@ -81,9 +79,6 @@
 #define CONFIG_CMD_MEMORY
 #define CONFIG_CMD_SETEXPR
 
-#define CONFIG_PARTITION_UUIDS
-#define CONFIG_CMD_PART
-
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_CMDLINE_TAG
 #define CONFIG_INITRD_TAG
@@ -145,10 +140,10 @@
 #define CONFIG_SPL_SERIAL_SUPPORT
 #define CONFIG_SPL_LIBGENERIC_SUPPORT
 
+#define CONFIG_SPL_BOARD_LOAD_IMAGE
+
 #ifdef CONFIG_SPL_FEL
 
-#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds"
-#define CONFIG_SPL_START_S_PATH "arch/arm/cpu/armv7/sunxi"
 #define CONFIG_SPL_TEXT_BASE		0x2000
 #define CONFIG_SPL_MAX_SIZE		0x4000		/* 16 KiB */
 
@@ -206,10 +201,10 @@
 
 #ifdef CONFIG_VIDEO
 /*
- * The amount of RAM that is reserved for the FB. This will not show up as
- * RAM to the kernel, but will be reclaimed by a KMS driver in future.
+ * The amount of RAM to keep free at the top of RAM when relocating u-boot,
+ * to use as framebuffer. This must be a multiple of 4096.
  */
-#define CONFIG_SUNXI_FB_SIZE (9 << 20)
+#define CONFIG_SUNXI_MAX_FB_SIZE (9 << 20)
 
 /* Do we want to initialize a simple FB? */
 #define CONFIG_VIDEO_DT_SIMPLEFB
@@ -227,8 +222,6 @@
 /* stop x86 thinking in cfbconsole from trying to init a pc keyboard */
 #define CONFIG_VGA_AS_SINGLE_DEVICE
 
-#define CONFIG_SYS_MEM_TOP_HIDE ((CONFIG_SUNXI_FB_SIZE + 0xFFF) & ~0xFFF)
-
 /* To be able to hook simplefb into dt */
 #ifdef CONFIG_VIDEO_DT_SIMPLEFB
 #define CONFIG_OF_BOARD_SETUP
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index e4b9881..cc189ad 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -154,10 +154,8 @@
 endif
 
 ifdef CONFIG_SUNXI
-ifndef CONFIG_SPL_FEL
 ALL-y	+= $(obj)/sunxi-spl.bin
 endif
-endif
 
 ifeq ($(CONFIG_SYS_SOC),"at91")
 ALL-y	+= boot.bin
diff --git a/tools/Makefile b/tools/Makefile
index e4b23eb..88770b0 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -128,8 +128,6 @@
 HOSTLOADLIBES_fit_info := $(HOSTLOADLIBES_mkimage)
 HOSTLOADLIBES_fit_check_sign := $(HOSTLOADLIBES_mkimage)
 
-HOSTLDFLAGS += -T $(srctree)/tools/imagetool.lds
-
 hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl
 hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl
 HOSTCFLAGS_mkexynosspl.o := -pedantic
diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
index c9b9f6a..6f216f9 100644
--- a/tools/env/fw_env.config
+++ b/tools/env/fw_env.config
@@ -20,3 +20,6 @@
 
 # Block device example
 #/dev/mmcblk0		0xc0000		0x20000
+
+# VFAT example
+#/boot/uboot.env	0x0000          0x4000
diff --git a/tools/imagetool.c b/tools/imagetool.c
index 148e466..4b0b73d 100644
--- a/tools/imagetool.c
+++ b/tools/imagetool.c
@@ -12,16 +12,16 @@
 
 struct image_type_params *imagetool_get_type(int type)
 {
-	struct image_type_params *curr;
-	struct image_type_params *start = ll_entry_start(
-			struct image_type_params, image_type);
-	struct image_type_params *end = ll_entry_end(
-			struct image_type_params, image_type);
+	struct image_type_params **curr;
+	INIT_SECTION(image_type);
+
+	struct image_type_params **start = __start_image_type;
+	struct image_type_params **end = __stop_image_type;
 
 	for (curr = start; curr != end; curr++) {
-		if (curr->check_image_type) {
-			if (!curr->check_image_type(type))
-				return curr;
+		if ((*curr)->check_image_type) {
+			if (!(*curr)->check_image_type(type))
+				return *curr;
 		}
 	}
 	return NULL;
@@ -34,16 +34,15 @@
 	struct image_tool_params *params)
 {
 	int retval = -1;
-	struct image_type_params *curr;
+	struct image_type_params **curr;
+	INIT_SECTION(image_type);
 
-	struct image_type_params *start = ll_entry_start(
-			struct image_type_params, image_type);
-	struct image_type_params *end = ll_entry_end(
-			struct image_type_params, image_type);
+	struct image_type_params **start = __start_image_type;
+	struct image_type_params **end = __stop_image_type;
 
 	for (curr = start; curr != end; curr++) {
-		if (curr->verify_header) {
-			retval = curr->verify_header((unsigned char *)ptr,
+		if ((*curr)->verify_header) {
+			retval = (*curr)->verify_header((unsigned char *)ptr,
 						     sbuf->st_size, params);
 
 			if (retval == 0) {
@@ -51,12 +50,12 @@
 				 * Print the image information  if verify is
 				 * successful
 				 */
-				if (curr->print_header) {
-					curr->print_header(ptr);
+				if ((*curr)->print_header) {
+					(*curr)->print_header(ptr);
 				} else {
 					fprintf(stderr,
 						"%s: print_header undefined for %s\n",
-						params->cmdname, curr->name);
+						params->cmdname, (*curr)->name);
 				}
 				break;
 			}
diff --git a/tools/imagetool.h b/tools/imagetool.h
index f35dec7..3e15b4e 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -20,15 +20,6 @@
 #include <unistd.h>
 #include <u-boot/sha1.h>
 
-/* define __KERNEL__ in order to get the definitions
- * required by the linker list. This is probably not
- * the best way to do this */
-#ifndef __KERNEL__
-#define __KERNEL__
-#include <linker_lists.h>
-#undef __KERNEL__
-#endif /* __KERNEL__ */
-
 #include "fdt_host.h"
 
 #define ARRAY_SIZE(x)		(sizeof(x) / sizeof((x)[0]))
@@ -194,6 +185,46 @@
 
 void pbl_load_uboot(int fd, struct image_tool_params *mparams);
 
+#define ___cat(a, b) a ## b
+#define __cat(a, b) ___cat(a, b)
+
+/* we need some special handling for this host tool running eventually on
+ * Darwin. The Mach-O section handling is a bit different than ELF section
+ * handling. The differnces in detail are:
+ *  a) we have segments which have sections
+ *  b) we need a API call to get the respective section symbols */
+#if defined(__MACH__)
+#include <mach-o/getsect.h>
+
+#define INIT_SECTION(name)  do {					\
+		unsigned long name ## _len;				\
+		char *__cat(pstart_, name) = getsectdata("__TEXT",	\
+			#name, &__cat(name, _len));			\
+		char *__cat(pstop_, name) = __cat(pstart_, name) +	\
+			__cat(name, _len);				\
+		__cat(__start_, name) = (void *)__cat(pstart_, name);	\
+		__cat(__stop_, name) = (void *)__cat(pstop_, name);	\
+	} while (0)
+#define SECTION(name)   __attribute__((section("__TEXT, " #name)))
+
+struct image_type_params **__start_image_type, **__stop_image_type;
+#else
+#define INIT_SECTION(name) /* no-op for ELF */
+#define SECTION(name)   __attribute__((section(#name)))
+
+/* We construct a table of pointers in an ELF section (pointers generally
+ * go unpadded by gcc).  ld creates boundary syms for us. */
+extern struct image_type_params *__start_image_type[], *__stop_image_type[];
+#endif /* __MACH__ */
+
+#if !defined(__used)
+# if __GNUC__ == 3 && __GNUC_MINOR__ < 3
+#  define __used			__attribute__((__unused__))
+# else
+#  define __used			__attribute__((__used__))
+# endif
+#endif
+
 #define U_BOOT_IMAGE_TYPE( \
 		_id, \
 		_name, \
@@ -208,7 +239,8 @@
 		_fflag_handle, \
 		_vrec_header \
 	) \
-	ll_entry_declare(struct image_type_params, _id, image_type) = { \
+	static struct image_type_params __cat(image_type_, _id) = \
+	{ \
 		.name = _name, \
 		.header_size = _header_size, \
 		.hdr = _header, \
@@ -220,6 +252,8 @@
 		.check_image_type = _check_image_type, \
 		.fflag_handle = _fflag_handle, \
 		.vrec_header = _vrec_header \
-	}
+	}; \
+	static struct image_type_params *SECTION(image_type) __used \
+		__cat(image_type_ptr_, _id) = &__cat(image_type_, _id)
 
 #endif /* _IMAGETOOL_H_ */
diff --git a/tools/imagetool.lds b/tools/imagetool.lds
deleted file mode 100644
index 7e92b4a..0000000
--- a/tools/imagetool.lds
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2011-2012 The Chromium OS Authors.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-SECTIONS
-{
-
-	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*)));
-	}
-
-	__u_boot_sandbox_option_start = .;
-	_u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) }
-	__u_boot_sandbox_option_end = .;
-
-	__bss_start = .;
-}
-
-INSERT BEFORE .data;
diff --git a/tools/mksunxiboot.c b/tools/mksunxiboot.c
index 1f0fbae..0035f6e 100644
--- a/tools/mksunxiboot.c
+++ b/tools/mksunxiboot.c
@@ -43,19 +43,19 @@
 	uint32_t i;
 	uint32_t sum;
 
-	length = head_p->length;
+	length = le32_to_cpu(head_p->length);
 	if ((length & 0x3) != 0)	/* must 4-byte-aligned */
 		return -1;
 	buf = (uint32_t *)head_p;
-	head_p->check_sum = STAMP_VALUE;	/* fill stamp */
+	head_p->check_sum = cpu_to_le32(STAMP_VALUE);	/* fill stamp */
 	loop = length >> 2;
 
 	/* calculate the sum */
 	for (i = 0, sum = 0; i < loop; i++)
-		sum += buf[i];
+		sum += le32_to_cpu(buf[i]);
 
 	/* write back check sum */
-	head_p->check_sum = sum;
+	head_p->check_sum = cpu_to_le32(sum);
 
 	return 0;
 }
@@ -125,10 +125,12 @@
 	memcpy(img.header.magic, BOOT0_MAGIC, 8);	/* no '0' termination */
 	img.header.length =
 		ALIGN(file_size + sizeof(struct boot_file_head), BLOCK_SIZE);
+	img.header.b_instruction = cpu_to_le32(img.header.b_instruction);
+	img.header.length = cpu_to_le32(img.header.length);
 	gen_check_sum(&img.header);
 
-	count = write(fd_out, &img, img.header.length);
-	if (count != img.header.length) {
+	count = write(fd_out, &img, le32_to_cpu(img.header.length));
+	if (count != le32_to_cpu(img.header.length)) {
 		perror("Writing output");
 		return EXIT_FAILURE;
 	}