diff --git a/board/freescale/mpc8610hpcd/mpc8610hpcd.c b/board/freescale/mpc8610hpcd/mpc8610hpcd.c
index 784a2ed686d28979cef48b8db52ad58e8eecd6ee..ab5f800453b6043a42ee86df90ec8b5502a3994c 100644
--- a/board/freescale/mpc8610hpcd/mpc8610hpcd.c
+++ b/board/freescale/mpc8610hpcd/mpc8610hpcd.c
@@ -127,6 +127,8 @@ initdram(int board_type)
 	dram_size = fixed_sdram();
 #endif
 
+	setup_ddr_bat(dram_size);
+
 	puts(" DDR: ");
 	return dram_size;
 }
diff --git a/board/freescale/mpc8641hpcn/mpc8641hpcn.c b/board/freescale/mpc8641hpcn/mpc8641hpcn.c
index c521527d890b4a27264dfbfdf73ac9f718bb0e3b..443c9fd8ec4f036695f77f920d3fd170d19b8fe1 100644
--- a/board/freescale/mpc8641hpcn/mpc8641hpcn.c
+++ b/board/freescale/mpc8641hpcn/mpc8641hpcn.c
@@ -74,6 +74,8 @@ initdram(int board_type)
 	dram_size = fixed_sdram();
 #endif
 
+	setup_ddr_bat(dram_size);
+
 	puts("    DDR: ");
 	return dram_size;
 }
diff --git a/cpu/mpc86xx/cpu.c b/cpu/mpc86xx/cpu.c
index f7e012db573cc0f795291f32dd3b2b9fae0c89c3..188757587f5272ed246cdf55e7bebf63b209c7a8 100644
--- a/cpu/mpc86xx/cpu.c
+++ b/cpu/mpc86xx/cpu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006,2009 Freescale Semiconductor, Inc.
+ * Copyright 2006,2009-2010 Freescale Semiconductor, Inc.
  * Jeff Brown
  * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
  *
@@ -197,3 +197,37 @@ void mpc86xx_reginfo(void)
 	printf("\tBR7\t0x%08X\tOR7\t0x%08X \n", in_be32(&lbc->br7), in_be32(&lbc->or7));
 
 }
+
+/*
+ * Set the DDR BATs to reflect the actual size of DDR.
+ *
+ * dram_size is the actual size of DDR, in bytes
+ *
+ * Note: we assume that CONFIG_MAX_MEM_MAPPED is 2G or smaller as we only
+ * are using a single BAT to cover DDR.
+ *
+ * If this is not true, (e.g. CONFIG_MAX_MEM_MAPPED is 2GB but HID0_XBSEN
+ * is not defined) then we might have a situation where U-Boot will attempt
+ * to relocated itself outside of the region mapped by DBAT0.
+ * This will cause a machine check.
+ *
+ * Currently we are limited to power of two sized DDR since we only use a
+ * single bat.  If a non-power of two size is used that is less than
+ * CONFIG_MAX_MEM_MAPPED u-boot will crash.
+ *
+ */
+void setup_ddr_bat(phys_addr_t dram_size)
+{
+	unsigned long batu, bl;
+
+	bl = TO_BATU_BL(min(dram_size, CONFIG_MAX_MEM_MAPPED));
+
+	if (BATU_SIZE(bl) != dram_size) {
+		u64 sz = (u64)dram_size - BATU_SIZE(bl);
+		print_size(sz, " left unmapped\n");
+	}
+
+	batu = bl | BATU_VS | BATU_VP;
+	write_bat(DBAT0, batu, CONFIG_SYS_DBAT0L);
+	write_bat(IBAT0, batu, CONFIG_SYS_IBAT0L);
+}
diff --git a/cpu/mpc86xx/cpu_init.c b/cpu/mpc86xx/cpu_init.c
index 5a78a9cdc7458a769f39be1d0efd284b41cb0062..b4f047d85d071707289958cb35d84848a255967b 100644
--- a/cpu/mpc86xx/cpu_init.c
+++ b/cpu/mpc86xx/cpu_init.c
@@ -138,8 +138,12 @@ int cpu_init_r(void)
 /* Set up BAT registers */
 void setup_bats(void)
 {
+#if defined(CONFIG_SYS_DBAT0U) && defined(CONFIG_SYS_DBAT0L)
 	write_bat(DBAT0, CONFIG_SYS_DBAT0U, CONFIG_SYS_DBAT0L);
+#endif
+#if defined(CONFIG_SYS_IBAT0U) && defined(CONFIG_SYS_IBAT0L)
 	write_bat(IBAT0, CONFIG_SYS_IBAT0U, CONFIG_SYS_IBAT0L);
+#endif
 	write_bat(DBAT1, CONFIG_SYS_DBAT1U, CONFIG_SYS_DBAT1L);
 	write_bat(IBAT1, CONFIG_SYS_IBAT1U, CONFIG_SYS_IBAT1L);
 	write_bat(DBAT2, CONFIG_SYS_DBAT2U, CONFIG_SYS_DBAT2L);
diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
index fd1024947d94e58e3725f4505198a142fd357e3f..ce7f0810051d67daea5b2a26eeba282c34b71f59 100644
--- a/include/asm-ppc/mmu.h
+++ b/include/asm-ppc/mmu.h
@@ -213,7 +213,11 @@ extern void print_bats(void);
 #define BATL_PADDR(x) ((phys_addr_t)((x & 0xfffe0000)		\
 				     | ((x & 0x0e00ULL) << 24)	\
 				     | ((x & 0x04ULL) << 30)))
-#define BATU_SIZE(x) (1UL << (fls((x & BATU_BL_MAX) >> 2) + 17))
+#define BATU_SIZE(x) (1ULL << (fls((x & BATU_BL_MAX) >> 2) + 17))
+
+/* bytes into BATU_BL */
+#define TO_BATU_BL(x) \
+	(u32)((((1ull << __ilog2_u64((u64)x)) / (128 * 1024)) - 1) * 4)
 
 /* Used to set up SDR1 register */
 #define HASH_TABLE_SIZE_64K	0x00010000
diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h
index 1d2d659239f24851bbb92272e750907e8f8f3aa7..fed441eb37c4914ea6a92b896ef845b2811a47a8 100644
--- a/include/configs/MPC8610HPCD.h
+++ b/include/configs/MPC8610HPCD.h
@@ -341,10 +341,8 @@
  * BAT0		2G	Cacheable, non-guarded
  * 0x0000_0000	2G	DDR
  */
-#define CONFIG_SYS_DBAT0L	(BATL_PP_RW | BATL_MEMCOHERENCE)
-#define CONFIG_SYS_DBAT0U	(BATU_BL_2G | BATU_VS | BATU_VP)
-#define CONFIG_SYS_IBAT0L	(BATL_PP_RW | BATL_MEMCOHERENCE )
-#define CONFIG_SYS_IBAT0U	CONFIG_SYS_DBAT0U
+#define CONFIG_SYS_DBAT0L	(BATL_PP_RW)
+#define CONFIG_SYS_IBAT0L	(BATL_PP_RW)
 
 /*
  * BAT1		1G	Cache-inhibited, guarded
diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h
index 12a8f603900f85a4407518075ffa410aba06e4c8..94e4d243e86903ff5e74ae7208ad7b7157759ee7 100644
--- a/include/configs/MPC8641HPCN.h
+++ b/include/configs/MPC8641HPCN.h
@@ -482,9 +482,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
  * BAT0		DDR
  */
 #define CONFIG_SYS_DBAT0L	(BATL_PP_RW | BATL_MEMCOHERENCE)
-#define CONFIG_SYS_DBAT0U	(BATU_BL_2G | BATU_VS | BATU_VP)
-#define CONFIG_SYS_IBAT0L	(BATL_PP_RW | BATL_MEMCOHERENCE )
-#define CONFIG_SYS_IBAT0U	CONFIG_SYS_DBAT0U
+#define CONFIG_SYS_IBAT0L	(BATL_PP_RW | BATL_MEMCOHERENCE)
 
 /*
  * BAT1		LBC (PIXIS/CF)
diff --git a/include/mpc86xx.h b/include/mpc86xx.h
index c6f30f9fd5a7dc91250712e7529f47d817f9c74b..eb85d60cad1bfa3688d70adbaa446a44e0497b6c 100644
--- a/include/mpc86xx.h
+++ b/include/mpc86xx.h
@@ -83,5 +83,7 @@ static __inline__ unsigned long get_l2cr (void)
    return l2cr_val;
 }
 
+void setup_ddr_bat(phys_addr_t dram_size);
+
 #endif  /* _ASMLANGUAGE */
 #endif	/* __MPC86xx_H__ */